Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add pattern: lazy_evaluation
* add pattern.
* update readme, sorted by alphabet.
  • Loading branch information
lord63 committed Apr 1, 2015
commit babfa91722721884b8c9769452c5e9e07fc31972
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ Current Patterns:
| [builder](builder.py) | call many little discrete methods rather than having a huge number of constructor parameters |
| [catalog](catalog.py) | general methods will call different specialized methods based on construction parameter |
| [chain](chain.py) | apply a chain of successive handlers to try and process the data |
| [chaining_method](chaining_method.py) | continue callback next object method |
| [command](command.py) | bundle a command and arguments to call later |
| [composite](composite.py) | encapsulate and provide access to a number of different objects |
| [decorator](decorator.py) | wrap functionality with other functionality in order to affect outputs |
| [facade](facade.py) | use one class as an API to a number of others |
| [factory_method](factory_method.py) | delegate a specialized function/method to create instances |
| [flyweight](flyweight.py) | transparently reuse existing instances of objects with similar/identical state |
| [graph_search](graph_search.py) | (graphing algorithms, not design patterns) |
| [lazy_evaluation](lazy_evaluation.py) | lazily-evaluated property pattern in Python |
| [mediator](mediator.py) | an object that knows how to connect other objects and act as a proxy |
| [memento](memento.py) | generate an opaque token that can be used to go back to a previous state |
| [mvc](mvc.py) | model<->view<->controller (non-strict relationships) |
Expand All @@ -38,4 +40,3 @@ Current Patterns:
| [strategy](strategy.py) | selectable operations over the same data |
| [template](template.py) | an object imposes a structure but takes pluggable components |
| [visitor](visitor.py) | invoke a callback for all items of a collection |
| [chaining_method](chaining_method.py) | continue callback next object method |
55 changes: 55 additions & 0 deletions lazy_evaluation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Lazily-evaluated property pattern in Python.

https://en.wikipedia.org/wiki/Lazy_evaluation
http://stevenloria.com/lazy-evaluated-properties-in-python/
"""


def lazy_property(fn):
"""Decorator that makes a property lazy-evaluated."""
attr_name = '_lazy_' + fn.__name__

@property
def _lazy_property(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, fn(self))
return getattr(self, attr_name)
return _lazy_property


class Person(object):
def __init__(self, name, occupation):
self.name = name
self.occupation = occupation

@lazy_property
def relatives(self):
# Get all relatives, let's assume that it costs much time.
relatives = "Many relatives."
return relatives


def main():
Jhon = Person('Jhon', 'Coder')
print("Name: {0} Occupation: {1}".format(Jhon.name, Jhon.occupation))
print("Before we access `relatives`:")
print(Jhon.__dict__)
print("Jhon's relatives: {0}".format(Jhon.relatives))
print("After we've accessed `relatives`:")
print(Jhon.__dict__)


if __name__ == '__main__':
main()

### OUTPUT ###
# Name: Jhon Occupation: Coder
# Before we access `relatives`:
# {'name': 'Jhon', 'occupation': 'Coder'}
# Jhon's relatives: Many relatives.
# After we've accessed `relatives`:
# {'_lazy_relatives': 'Many relatives.', 'name': 'Jhon', 'occupation': 'Coder'}