From c5ef93096bea45737e79736faecfbcc4be4fac0b Mon Sep 17 00:00:00 2001 From: luoxing Date: Thu, 5 Mar 2015 05:16:26 +0800 Subject: [PATCH 1/2] clean --- composite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/composite.py b/composite.py index d49fc55bc..73cfa469d 100644 --- a/composite.py +++ b/composite.py @@ -233,6 +233,7 @@ def getParent(self): return self._father def __setChildDict(self, child): + """ Private method to set the dictionary of the child object 'child' in the internal dictionary """ From 98fb39fcbd0f6b04cb50d0dcf246147dab74833d Mon Sep 17 00:00:00 2001 From: luoxing Date: Thu, 5 Mar 2015 05:20:03 +0800 Subject: [PATCH 2/2] ok --- README.md | 2 +- abstract_factory.py | 12 +++++++++--- adapter.py | 18 +++++++++--------- catalog.py | 18 +++++++++--------- chaining_method.py | 33 +++++++++++++++++++++++++++++++++ composite.py | 35 +++++++++++++---------------------- decorator.py | 9 ++++++--- factory_method.py | 2 +- graph_search.py | 32 ++++++++++++++++---------------- iterator.py | 37 +++++++++++++++++++++++++++++++++++++ prototype.py | 1 + publish_subscribe.py | 15 +++++++-------- 12 files changed, 142 insertions(+), 72 deletions(-) create mode 100644 chaining_method.py create mode 100644 iterator.py diff --git a/README.md b/README.md index 35e83733b..1fdee48a2 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ 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) | -| [iterator](iterator.py) | structure repeated, identical calls as a generator | | [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) | @@ -39,3 +38,4 @@ 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/abstract_factory.py b/abstract_factory.py index 72d57043d..a32c067e6 100644 --- a/abstract_factory.py +++ b/abstract_factory.py @@ -52,12 +52,18 @@ class DogFactory: def get_pet(self): return Dog() + def get_food(self): + return "dog food" + class CatFactory: def get_pet(self): return Cat() + def get_food(self): + return "cat food" + # Create the proper family def get_factory(): """Let's be dynamic!""" @@ -80,7 +86,7 @@ def get_factory(): # It says woof # We also have dog food # ==================== -# We have a lovely Dog -# It says woof -# We also have dog food +# We have a lovely Cat +# It says meow +# We also have cat food # ==================== diff --git a/adapter.py b/adapter.py index 1620ce4c4..fedbd8c16 100644 --- a/adapter.py +++ b/adapter.py @@ -41,14 +41,14 @@ class Adapter(object): >>> objects = [] >>> dog = Dog() - >>> objects.append(Adapter(dog, dict(make_noise=dog.bark))) + >>> objects.append(Adapter(dog, make_noise=dog.bark)) >>> cat = Cat() - >>> objects.append(Adapter(cat, dict(make_noise=cat.meow))) + >>> objects.append(Adapter(cat, make_noise=cat.meow)) >>> human = Human() - >>> objects.append(Adapter(human, dict(make_noise=human.speak))) + >>> objects.append(Adapter(human, make_noise=human.speak)) >>> car = Car() >>> car_noise = lambda: car.make_noise(3) - >>> objects.append(Adapter(car, dict(make_noise=car_noise))) + >>> objects.append(Adapter(car, make_noise=car_noise)) >>> for obj in objects: ... print('A {} goes {}'.format(obj.name, obj.make_noise())) @@ -58,7 +58,7 @@ class Adapter(object): A Car goes vroom!!! """ - def __init__(self, obj, adapted_methods): + def __init__(self, obj, **adapted_methods): """We set the adapted methods in the object's dict""" self.obj = obj self.__dict__.update(adapted_methods) @@ -71,13 +71,13 @@ def __getattr__(self, attr): def main(): objects = [] dog = Dog() - objects.append(Adapter(dog, dict(make_noise=dog.bark))) + objects.append(Adapter(dog, make_noise=dog.bark)) cat = Cat() - objects.append(Adapter(cat, dict(make_noise=cat.meow))) + objects.append(Adapter(cat, make_noise=cat.meow)) human = Human() - objects.append(Adapter(human, dict(make_noise=human.speak))) + objects.append(Adapter(human, make_noise=human.speak)) car = Car() - objects.append(Adapter(car, dict(make_noise=lambda: car.make_noise(3)))) + objects.append(Adapter(car, make_noise=lambda: car.make_noise(3))) for obj in objects: print("A {0} goes {1}".format(obj.name, obj.make_noise())) diff --git a/catalog.py b/catalog.py index bc6debba0..8bfdf921e 100644 --- a/catalog.py +++ b/catalog.py @@ -3,7 +3,7 @@ """ A class that uses different static function depending of a parameter passed in -init. Note the use of a single dictionnary instead of multiple conditions +init. Note the use of a single dictionary instead of multiple conditions """ __author__ = "Ibrahim Diop " __gist__ = "" @@ -21,29 +21,29 @@ def __init__(self, param): # dictionary that will be used to determine which static method is # to be executed but that will be also used to store possible param # value - self.static_method_choices = {'param_value_1': self.static_method_1, - 'param_value_2': self.static_method_2} + self._static_method_choices = {'param_value_1': self._static_method_1, + 'param_value_2': self._static_method_2} # simple test to validate param value - if param in self.static_method_choices.keys(): + if param in self._static_method_choices.keys(): self.param = param else: - raise Exception("Invalid Value for Param: {0}".format(param)) + raise ValueError("Invalid Value for Param: {0}".format(param)) @staticmethod - def static_method_1(): + def _static_method_1(): print("executed method 1!") @staticmethod - def static_method_2(): + def _static_method_2(): print("executed method 2!") def main_method(self): """ - will execute either static_method_1 or static_method_2 + will execute either _static_method_1 or _static_method_2 depending on self.param value """ - self.static_method_choices[self.param]() + self._static_method_choices[self.param]() def main(): diff --git a/chaining_method.py b/chaining_method.py new file mode 100644 index 000000000..e03747618 --- /dev/null +++ b/chaining_method.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +class Person(object): + + def __init__(self, name, action): + self.name = name + self.action = action + + def do_action(self): + print(self.name, self.action.name, end=' ') + return self.action + +class Action(object): + + def __init__(self, name): + self.name = name + + def amount(self, val): + print(val, end=' ') + return self + + def stop(self): + print('then stop') + +if __name__ == '__main__': + + move = Action('move') + person = Person('Jack', move) + person.do_action().amount('5m').stop() + +### OUTPUT ### +# Jack move 5m then stop diff --git a/composite.py b/composite.py index 73cfa469d..7af8b6c1d 100644 --- a/composite.py +++ b/composite.py @@ -5,10 +5,11 @@ A class which defines a composite object which can store hieararchical dictionaries with names. -This class is same as a hiearchical dictionary, but it provides methods -to add/access/modify children by name, like a Composite. +This class is same as a hiearchical dictionary, but it +provides methods to add/access/modify children by name, +like a Composite. -Created Anand B Pillai +Created Anand B Pillai """ __author__ = "Anand B Pillai" @@ -17,10 +18,8 @@ def normalize(val): - """Normalize a string so that it can be used as an attribute to a Python - - object - """ + """ Normalize a string so that it can be used as an attribute + to a Python object """ if val.find('-') != -1: val = val.replace('-', '_') @@ -39,7 +38,8 @@ def denormalize(val): class SpecialDict(dict): - """A dictionary type which allows direct attribute access to its keys """ + """ A dictionary type which allows direct attribute + access to its keys """ def __getattr__(self, name): @@ -127,13 +127,11 @@ def isLeaf(self): return not self._children def getName(self): - """ Return the name of this ConfigInfo object """ return self._name def getIndex(self, child): - """ Return the index of the child ConfigInfo object 'child' """ if child in self._children: @@ -147,17 +145,17 @@ def getDict(self): return self[self._name] def getProperty(self, child, key): - - """Return the value for the property for child 'child' with key 'key' """ + """ Return the value for the property for child + 'child' with key 'key' """ # First get the child's dictionary childDict = self.getInfoDict(child) if childDict: return childDict.get(key, None) - def setProperty(self, child, key, value): - - """Set the value for the property 'key' for the child 'child' to 'value' """ + def setProperty(self, child, key, value): + """ Set the value for the property 'key' for + the child 'child' to 'value' """ # First get the child's dictionary childDict = self.getInfoDict(child) @@ -165,13 +163,11 @@ def setProperty(self, child, key, value): childDict[key] = value def getChildren(self): - """ Return the list of immediate children of this object """ return self._children def getAllChildren(self): - """ Return the list of all children of this object """ l = [] @@ -182,7 +178,6 @@ def getAllChildren(self): return l def getChild(self, name): - """ Return the immediate child object with the given name """ for child in self._children: @@ -190,7 +185,6 @@ def getChild(self, name): return child def findChild(self, name): - """ Return the child with the given name from the tree """ # Note - this returns the first child of the given name @@ -202,7 +196,6 @@ def findChild(self, name): return child def findChildren(self, name): - """ Return a list of children with the given name from the tree """ # Note: this returns a list of all the children of a given @@ -217,7 +210,6 @@ def findChildren(self, name): return children def getPropertyDict(self): - """ Return the property dictionary """ d = self.getChild('__properties') @@ -227,7 +219,6 @@ def getPropertyDict(self): return {} def getParent(self): - """ Return the person who created me """ return self._father diff --git a/decorator.py b/decorator.py index 8c365b7b4..ce96f3153 100644 --- a/decorator.py +++ b/decorator.py @@ -1,24 +1,27 @@ -'''https://docs.python.org/2/library/functools.html#functools.wraps''' -'''https://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python/739665#739665''' +"""https://docs.python.org/2/library/functools.html#functools.wraps""" +"""https://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python/739665#739665""" from functools import wraps + def makebold(fn): @wraps(fn) def wrapped(): return "" + fn() + "" return wrapped + def makeitalic(fn): @wraps(fn) def wrapped(): return "" + fn() + "" return wrapped + @makebold @makeitalic def hello(): - '''a decorated hello world''' + """a decorated hello world""" return "hello world" if __name__ == '__main__': diff --git a/factory_method.py b/factory_method.py index 65c2e8d28..c21e3960b 100644 --- a/factory_method.py +++ b/factory_method.py @@ -33,7 +33,7 @@ def get_localizer(language="English"): return languages[language]() # Create our localizers -e, g = get_localizer("English"), get_localizer("Greek") +e, g = get_localizer(language="English"), get_localizer(language="Greek") # Localize some text for msgid in "dog parrot cat bear".split(): print(e.get(msgid), g.get(msgid)) diff --git a/graph_search.py b/graph_search.py index df4f5342f..e76d2e390 100644 --- a/graph_search.py +++ b/graph_search.py @@ -10,10 +10,10 @@ class GraphSearch: def __init__(self, graph): self.graph = graph - def find_path(self, start, end, path=[]): + def find_path(self, start, end, path=None): self.start = start self.end = end - self.path = path + self.path = path if path else [] self.path += [self.start] if self.start == self.end: @@ -27,37 +27,37 @@ def find_path(self, start, end, path=[]): return newpath return None - def find_all_path(self, start, end, path=[]): + def find_all_path(self, start, end, path=None): self.start = start self.end = end - self.path = path - self.path += [self.start] + _path = path if path else [] + _path += [self.start] if self.start == self.end: - return [self.path] + return [_path] if self.start not in self.graph: return [] paths = [] for node in self.graph[self.start]: - if node not in self.path: - newpaths = self.find_all_path(node, self.end, self.path) + if node not in _path: + newpaths = self.find_all_path(node, self.end, _path[:]) for newpath in newpaths: paths.append(newpath) return paths - def find_shortest_path(self, start, end, path=[]): + def find_shortest_path(self, start, end, path=None): self.start = start self.end = end - self.path = path + _path = path if path else [] - self.path += [self.start] + _path += [self.start] if self.start == self.end: - return self.path + return _path if self.start not in self.graph: return None shortest = None for node in self.graph[self.start]: - if node not in self.path: - newpath = self.find_shortest_path(node, self.end, self.path) + if node not in _path: + newpath = self.find_shortest_path(node, self.end, _path[:]) if newpath: if not shortest or len(newpath) < len(shortest): shortest = newpath @@ -82,5 +82,5 @@ def find_shortest_path(self, start, end, path=[]): ### OUTPUT ### # ['A', 'B', 'C', 'D'] -# [['A', 'B', 'C', 'D']] -# ['A', 'B', 'C', 'D'] +# [['A', 'B', 'C', 'D'], ['A', 'B', 'D'], ['A', 'C', 'D']] +# ['A', 'B', 'D'] diff --git a/iterator.py b/iterator.py new file mode 100644 index 000000000..3aa36b8d4 --- /dev/null +++ b/iterator.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ + +Implementation of the iterator pattern with a generator""" + + +def count_to(count): + """Counts by word numbers, up to a maximum of five""" + numbers = ["one", "two", "three", "four", "five"] + # enumerate() returns a tuple containing a count (from start which + # defaults to 0) and the values obtained from iterating over sequence + for pos, number in zip(range(count), numbers): + yield number + +# Test the generator +count_to_two = lambda: count_to(2) +count_to_five = lambda: count_to(5) + +print('Counting to two...') +for number in count_to_two(): + print(number, end=' ') + +print() + +print('Counting to five...') +for number in count_to_five(): + print(number, end=' ') + +print() + +### OUTPUT ### +# Counting to two... +# one two +# Counting to five... +# one two three four five diff --git a/prototype.py b/prototype.py index cc88e24f7..2f2a14a82 100644 --- a/prototype.py +++ b/prototype.py @@ -23,6 +23,7 @@ def clone(self, name, **attr): obj.__dict__.update(attr) return obj + class A: def __init__(self): self.x = 3 diff --git a/publish_subscribe.py b/publish_subscribe.py index 522e9ea43..e88dd4f3c 100644 --- a/publish_subscribe.py +++ b/publish_subscribe.py @@ -10,8 +10,9 @@ class Provider: def __init__(self): - self.subscribe_queue = {} - self.msg_queue=[] + self.msg_queue = [] + self.subscribers = {} + def notify(self, msg): self.msg_queue.append(msg) @@ -24,14 +25,12 @@ def subscribe(self, msg, subscriber): def unsubscribe(self, msg, subscriber): self.subscribers[msg].remove(subscriber) - if !self.subscribe[msg]: - del self.subscribe[msg] def update(self): for msg in self.msg_queue: - if msg in self.subscribers.keys(): - for suber in self.subscribers[msg]: - suber.get(msg) + if msg in self.subscribers: + for sub in self.subscribers[msg]: + sub.run(msg) self.msg_queue = [] @@ -53,7 +52,7 @@ def __init__(self, name, msg_center): def subscribe(self, msg): self.provider.subscribe(msg, self) - def get(self, msg): + def run(self, msg): print("{} got {}".format(self.name, msg))