From babfa91722721884b8c9769452c5e9e07fc31972 Mon Sep 17 00:00:00 2001 From: lord63 Date: Wed, 1 Apr 2015 10:19:39 +0800 Subject: [PATCH] Add pattern: lazy_evaluation * add pattern. * update readme, sorted by alphabet. --- README.md | 3 ++- lazy_evaluation.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 lazy_evaluation.py diff --git a/README.md b/README.md index 1fdee48a2..985501026 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ 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 | @@ -26,6 +27,7 @@ Current Patterns: | [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) | @@ -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 | diff --git a/lazy_evaluation.py b/lazy_evaluation.py new file mode 100644 index 000000000..5f364a65d --- /dev/null +++ b/lazy_evaluation.py @@ -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'}