Python设计模式

这两天在PythonTip刷题,突然看到这里提供了Python的设计模式demo,正是我多年来想找的东西。

PythonTip
Python设计模式

于是乎,我就动用了我的爬爬爬爬爬虫把这些代码都爬下来了,放到简书,有时间就过来看看。25种设计模式,还是挺多的。

borg

class Borg:
    __shared_state = {}

    def __init__(self):
        self.__dict__ = self.__shared_state

    def __str__(self):
        return self.state


class YourBorg(Borg):
    pass

if __name__ == '__main__':
    rm1 = Borg()
    rm2 = Borg()

    rm1.state = 'Idle'
    rm2.state = 'Running'

    print('rm1:', rm1)
    print('rm2:', rm2)

    rm2.state = 'Zombie'

    print('rm1:', rm1)
    print('rm2:', rm2)

    print('rm1 id:', id(rm1))
    print('rm2 id:', id(rm2))

    rm3 = YourBorg()

    print('rm1:', rm1)
    print('rm2:', rm2)
    print('rm3:', rm3)


facade

"""http://dpip.testingperspective.com/?p=26"""

import time

SLEEP = 0.5


# Complex Parts
class TC1:
    def run(self):
        print("###### In Test 1 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC2:
    def run(self):
        print("###### In Test 2 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC3:
    def run(self):
        print("###### In Test 3 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


# Facade
class TestRunner:
    def __init__(self):
        self.tc1 = TC1()
        self.tc2 = TC2()
        self.tc3 = TC3()
        self.tests = [i for i in (self.tc1, self.tc2, self.tc3)]

    def runAll(self):
        [i.run() for i in self.tests]


# Client
if __name__ == '__main__':
    testrunner = TestRunner()
    testrunner.runAll()


chain

# http://www.testingperspective.com/wiki/doku.php/collaboration/chetan/designpatternsinpython/chain-of-responsibilitypattern


class Handler:
    def successor(self, successor):
        self.successor = successor


class ConcreteHandler1(Handler):
    def handle(self, request):
        if request > 0 and request <= 10:
            print("in handler1")
        else:
            self.successor.handle(request)
 

class ConcreteHandler2(Handler):
    def handle(self, request):
        if request > 10 and request <= 20:
            print("in handler2")
        else:
            self.successor.handle(request)
 

class ConcreteHandler3(Handler):
    def handle(self, request):
        if request > 20 and request <= 30:
            print("in handler3")
        else:
            print('end of chain, no handler for {}'.format(request))
 

class Client:
    def __init__(self):
        h1 = ConcreteHandler1()
        h2 = ConcreteHandler2()
        h3 = ConcreteHandler3()

        h1.successor(h2)
        h2.successor(h3)

        requests = [2, 5, 14, 22, 18, 3, 35, 27, 20]
        for request in requests:
            h1.handle(request)


if __name__ == "__main__":
    client = Client()


abstract_factory

# http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/

"""Implementation of the abstract factory pattern"""

import random


class PetShop:
    """A pet shop"""

    def __init__(self, animal_factory=None):
        """pet_factory is our abstract factory.
        We can set it at will."""

        self.pet_factory = animal_factory

    def show_pet(self):
        """Creates and shows a pet using the
        abstract factory"""

        pet = self.pet_factory.get_pet()
        print("This is a lovely", pet)
        print("It says", pet.speak())
        print("It eats", self.pet_factory.get_food())


# Stuff that our factory makes

class Dog:
    def speak(self):
        return "woof"

    def __str__(self):
        return "Dog"


class Cat:
    def speak(self):
        return "meow"

    def __str__(self):
        return "Cat"


# Factory classes

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!"""
    return random.choice([DogFactory, CatFactory])()


# Show pets with various factories
if __name__ == "__main__":
    shop = PetShop()
    for i in range(3):
        shop.pet_factory = get_factory()
        shop.show_pet()
        print("=" * 20)


bridge

# http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Bridge_Pattern#Python


# ConcreteImplementor 1/2
class DrawingAPI1(object):
    def draw_circle(self, x, y, radius):
        print('API1.circle at {}:{} radius {}'.format(x, y, radius))


# ConcreteImplementor 2/2
class DrawingAPI2(object):
    def draw_circle(self, x, y, radius):
        print('API2.circle at {}:{} radius {}'.format(x, y, radius))


# Refined Abstraction
class CircleShape(object):
    def __init__(self, x, y, radius, drawing_api):
        self._x = x
        self._y = y
        self._radius = radius
        self._drawing_api = drawing_api
 
    # low-level i.e. Implementation specific
    def draw(self):
        self._drawing_api.draw_circle(self._x, self._y, self._radius)
 
    # high-level i.e. Abstraction specific
    def scale(self, pct):
        self._radius *= pct


def main():
    shapes = (
        CircleShape(1, 2, 3, DrawingAPI1()),
        CircleShape(5, 7, 11, DrawingAPI2())
    )
 
    for shape in shapes:
        shape.scale(2.5)
        shape.draw()
 

if __name__ == '__main__':
    main()


memento

"""code.activestate.com/recipes/413838-memento-closure/"""

import copy


def Memento(obj, deep=False):
    state = (copy.copy, copy.deepcopy)[bool(deep)](obj.__dict__)

    def Restore():
        obj.__dict__.clear()
        obj.__dict__.update(state)
    return Restore


class Transaction:
    """A transaction guard. This is really just
      syntactic suggar arount a memento closure.
      """
    deep = False

    def __init__(self, *targets):
        self.targets = targets
        self.Commit()

    def Commit(self):
        self.states = [Memento(target, self.deep) for target in self.targets]

    def Rollback(self):
        for st in self.states:
            st()


class transactional(object):
    """Adds transactional semantics to methods. Methods decorated  with
    @transactional will rollback to entry state upon exceptions.
    """
    def __init__(self, method):
        self.method = method

    def __get__(self, obj, T):
        def transaction(*args, **kwargs):
            state = Memento(obj)
            try:
                return self.method(obj, *args, **kwargs)
            except:
                state()
                raise
        return transaction


class NumObj(object):
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return '<%s: %r>' % (self.__class__.__name__, self.value)

    def Increment(self):
        self.value += 1

    @transactional
    def DoStuff(self):
        self.value = '1111'  # <- invalid value
        self.Increment()     # <- will fail and rollback


if __name__ == '__main__':
    n = NumObj(-1)
    print(n)
    t = Transaction(n)
    try:
        for i in range(3):
            n.Increment()
            print(n)
        t.Commit()
        print('-- commited')
        for i in range(3):
            n.Increment()
            print(n)
        n.value += 'x'  # will fail
        print(n)
    except:
        t.Rollback()
        print('-- rolled back')
    print(n)
    print('-- now doing stuff ...')
    try:
        n.DoStuff()
    except:
        print('-> doing stuff failed!')
        import traceback
        traceback.print_exc(0)
        pass
    print(n)


mediator

"""http://dpip.testingperspective.com/?p=28"""

import time 


class TC:
    def __init__(self):                         
        self._tm = tm                         
        self._bProblem = 0             

    def setup(self):                         
        print("Setting up the Test")                         
        time.sleep(1)                         
        self._tm.prepareReporting()   

    def execute(self):                         
        if not self._bProblem:                                      
            print("Executing the test")                                      
            time.sleep(1)                         
        else:                                      
            print("Problem in setup. Test not executed.")             

    def tearDown(self):                         
        if not self._bProblem:                                      
            print("Tearing down")                                      
            time.sleep(1)                                      
            self._tm.publishReport()                         
        else:                                      
            print("Test not executed. No tear down required.")             

    def setTM(self, TM):
        self._tm = tm             

    def setProblem(self, value):                         
        self._bProblem = value 


class Reporter:
    def __init__(self):                         
        self._tm = None             

    def prepare(self):                         
        print("Reporter Class is preparing to report the results")                         
        time.sleep(1)             

    def report(self):                         
        print("Reporting the results of Test")                         
        time.sleep(1)             

    def setTM(self, TM):
        self._tm = tm 


class DB:
    def __init__(self):                         
        self._tm = None             

    def insert(self):                         
        print("Inserting the execution begin status in the Database")                         
        time.sleep(1)                         
        #Following code is to simulate a communication from DB to TC                         
        import random                         
        if random.randrange(1, 4) == 3:
            return -1             

    def update(self):                         
        print("Updating the test results in Database")                         
        time.sleep(1)             

    def setTM(self, TM):
        self._tm = tm 


class TestManager:
    def __init__(self):                         
        self._reporter = None                         
        self._db = None                         
        self._tc = None             

    def prepareReporting(self):                         
        rvalue = self._db.insert()                         
        if rvalue == -1:                                      
            self._tc.setProblem(1)                                      
            self._reporter.prepare()             

    def setReporter(self, reporter):                         
        self._reporter = reporter             

    def setDB(self, db):                         
        self._db = db             

    def publishReport(self):                         
        self._db.update()                         
        rvalue = self._reporter.report()             

    def setTC(self, tc):
        self._tc = tc 


if __name__ == '__main__':             
    reporter = Reporter()             
    db = DB()             
    tm = TestManager()             
    tm.setReporter(reporter)             
    tm.setDB(db)             
    reporter.setTM(tm)             
    db.setTM(tm)             
    # For simplification we are looping on the same test.             
    # Practically, it could be about various unique test classes and their
    # objects
    while (True):                         
        tc = TC()                         
        tc.setTM(tm)                         
        tm.setTC(tc)                         
        tc.setup()                         
        tc.execute()                         
        tc.tearDown()


prototype

import copy


class Prototype:
    def __init__(self):
        self._objects = {}

    def register_object(self, name, obj):
        """Register an object"""
        self._objects[name] = obj

    def unregister_object(self, name):
        """Unregister an object"""
        del self._objects[name]

    def clone(self, name, **attr):
        """Clone a registered object and update inner attributes dictionary"""
        obj = copy.deepcopy(self._objects.get(name))
        obj.__dict__.update(attr)
        return obj


def main():
    class A:
        pass

    a = A()
    prototype = Prototype()
    prototype.register_object('a', a)
    b = prototype.clone('a', a=1, b=2, c=3)

    print(a)
    print(b.a, b.b, b.c)


if __name__ == '__main__':
    main()


decorator

# http://stackoverflow.com/questions/3118929/implementing-the-decorator-pattern-in-python


class foo(object):
    def f1(self):
        print("original f1")

    def f2(self):
        print("original f2")


class foo_decorator(object):
    def __init__(self, decoratee):
        self._decoratee = decoratee

    def f1(self):
        print("decorated f1")
        self._decoratee.f1()

    def __getattr__(self, name):
        return getattr(self._decoratee, name)

u = foo()
v = foo_decorator(u)
v.f1()
v.f2()


adapter

# http://ginstrom.com/scribbles/2008/11/06/generic-adapter-class-in-python/

import os


class Dog(object):
    def __init__(self):
        self.name = "Dog"

    def bark(self):
        return "woof!"


class Cat(object):
    def __init__(self):
        self.name = "Cat"

    def meow(self):
        return "meow!"


class Human(object):
    def __init__(self):
        self.name = "Human"

    def speak(self):
        return "'hello'"


class Car(object):
    def __init__(self):
        self.name = "Car"

    def make_noise(self, octane_level):
        return "vroom%s" % ("!" * octane_level)


class Adapter(object):
    """
    Adapts an object by replacing methods.
    Usage:
    dog = Dog
    dog = Adapter(dog, dict(make_noise=dog.bark))
    """
    def __init__(self, obj, adapted_methods):
        """We set the adapted methods in the object's dict"""
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        """All non-adapted calls are passed to the object"""
        return getattr(self.obj, attr)


def main():
    objects = []
    dog = Dog()
    objects.append(Adapter(dog, dict(make_noise=dog.bark)))
    cat = Cat()
    objects.append(Adapter(cat, dict(make_noise=cat.meow)))
    human = Human()
    objects.append(Adapter(human, dict(make_noise=human.speak)))
    car = Car()
    car_noise = lambda: car.make_noise(3)
    objects.append(Adapter(car, dict(make_noise=car_noise)))

    for obj in objects:
        print("A", obj.name, "goes", obj.make_noise())


if __name__ == "__main__":
    main()


factory_method

#encoding=utf-8
"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/"""


class GreekGetter:
    """A simple localizer a la gettext"""
    def __init__(self):
        self.trans = dict(dog="蟽魏蠉位慰蟼", cat="纬维蟿伪")

    def get(self, msgid):
        """We'll punt if we don't have a translation"""          
        try:
            return self.trans[msgid]
        except KeyError:
            return str(msgid)


class EnglishGetter:
    """Simply echoes the msg ids"""     
    def get(self, msgid):
        return str(msgid)


def get_localizer(language="English"):
    """The factory method"""
    languages = dict(English=EnglishGetter, Greek=GreekGetter)
    return languages[language]()

# Create our localizers
e, g = get_localizer("English"), get_localizer("Greek")
# Localize some text
for msgid in "dog parrot cat bear".split():
    print(e.get(msgid), g.get(msgid))


observer

"""http://code.activestate.com/recipes/131499-observer-pattern/"""


class Subject(object):
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        if not observer in self._observers:
            self._observers.append(observer)

    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass

    def notify(self, modifier=None):
        for observer in self._observers:
            if modifier != observer:
                observer.update(self)


# Example usage
class Data(Subject):
    def __init__(self, name=''):
        Subject.__init__(self)
        self.name = name
        self._data = 0

    @property
    def data(self):
        return self._data
    
    @data.setter
    def data(self, value):
        self._data = value
        self.notify()


class HexViewer:
    def update(self, subject):
        print('HexViewer: Subject %s has data 0x%x' %
              (subject.name, subject.data))


class DecimalViewer:
    def update(self, subject):
        print('DecimalViewer: Subject %s has data %d' %
              (subject.name, subject.data))


# Example usage...
def main():
    data1 = Data('Data 1')
    data2 = Data('Data 2')
    view1 = DecimalViewer()
    view2 = HexViewer()
    data1.attach(view1)
    data1.attach(view2)
    data2.attach(view2)
    data2.attach(view1)

    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15
    print("Setting Data 1 = 3")
    data1.data = 3
    print("Setting Data 2 = 5")
    data2.data = 5
    print("Detach HexViewer from data1 and data2.")
    data1.detach(view2)
    data2.detach(view2)
    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15


if __name__ == '__main__':
    main()


command

import os


class MoveFileCommand(object):
    def __init__(self, src, dest):
        self.src = src
        self.dest = dest

    def execute(self):
        self()
        
    def __call__(self):
        print('renaming {} to {}'.format(self.src, self.dest))
        os.rename(self.src, self.dest)

    def undo(self):
        print('renaming {} to {}'.format(self.dest, self.src))
        os.rename(self.dest, self.src)


if __name__ == "__main__":
    command_stack = []

    # commands are just pushed into the command stack
    command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
    command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))


    # they can be executed later on
    for cmd in command_stack:
        cmd.execute()

    # and can also be undone at will
    for cmd in reversed(command_stack):
        cmd.undo()


iterator

"""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()


template

"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/"""

"""An example of the Template pattern in Python"""  

ingredients = "spam eggs apple"
line = '-' * 10


# Skeletons
def iter_elements(getter, action):     
    """Template skeleton that iterates items"""      
    for element in getter():         
        action(element)     
        print(line)  


def rev_elements(getter, action):
    """Template skeleton that iterates items in reverse order"""      
    for element in getter()[::-1]:         
        action(element)     
        print(line)  


# Getters
def get_list():     
    return ingredients.split()  


def get_lists():
    return [list(x) for x in ingredients.split()]  


# Actions
def print_item(item):     
    print(item)  


def reverse_item(item):
    print(item[::-1])  


# Makes templates
def make_template(skeleton, getter, action):     
    """Instantiate a template method with getter and action"""     
    def template():         
        skeleton(getter, action)     
    return template  

# Create our template functions 
templates = [make_template(s, g, a)              
             for g in (get_list, get_lists)              
             for a in (print_item, reverse_item)              
             for s in (iter_elements, rev_elements)]  

# Execute them 
for template in templates:     
    template()


null

#!/user/bin/env python 

"""http://code.activestate.com/recipes/68205-null-object-design-pattern/"""


class Null:
    def __init__(self, *args, **kwargs):
        """Ignore parameters."""
        return None

    def __call__(self, *args, **kwargs):
        """Ignore method calls."""
        return self

    def __getattr__(self, mname):
        """Ignore attribute requests."""
        return self

    def __setattr__(self, name, value):
        """Ignore attribute setting."""
        return self

    def __delattr__(self, name):
        """Ignore deleting attributes."""
        return self

    def __repr__(self):
        """Return a string representation."""
        return "<Null>"

    def __str__(self):
        """Convert to a string and return it."""
        return "Null"


def test():
    """Perform some decent tests, or rather: demos."""

    # constructing and calling

    n = Null()
    print(n)

    n = Null('value')
    print(n)

    n = Null('value', param='value')
    print(n)

    n()
    n('value')
    n('value', param='value')
    print(n)

    # attribute handling

    n.attr1
    print('attr1', n.attr1)
    n.attr1.attr2
    n.method1()
    n.method1().method2()
    n.method('value')
    n.method(param='value')
    n.method('value', param='value')
    n.attr1.method1()
    n.method1().attr1

    n.attr1 = 'value'
    n.attr1.attr2 = 'value'

    del n.attr1
    del n.attr1.attr2.attr3

    # representation and conversion to a string
    
    assert repr(n) == '<Null>'
    assert str(n) == 'Null'


if __name__ == '__main__':
    test()


state

"""Implementation of the state pattern"""  

'''http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/'''


class State(object):
    """Base state. This is to share functionality"""      

    def scan(self):         
        """Scan the dial to the next station"""         
        self.pos += 1         
        if self.pos == len(self.stations):             
            self.pos = 0         
        print("Scanning... Station is", self.stations[self.pos], self.name)  


class AmState(State):
    def __init__(self, radio):         
        self.radio = radio         
        self.stations = ["1250", "1380", "1510"]         
        self.pos = 0         
        self.name = "AM"      

    def toggle_amfm(self):         
        print("Switching to FM")         
        self.radio.state = self.radio.fmstate  


class FmState(State):
    def __init__(self, radio):         
        self.radio = radio         
        self.stations = ["81.3", "89.1", "103.9"]         
        self.pos = 0         
        self.name = "FM"      

    def toggle_amfm(self):         
        print("Switching to AM")         
        self.radio.state = self.radio.amstate  


class Radio(object):
    """A radio.     It has a scan button, and an AM/FM toggle switch."""      
    def __init__(self):         
        """We have an AM state and an FM state"""          
        self.amstate = AmState(self)         
        self.fmstate = FmState(self)         
        self.state = self.amstate      

    def toggle_amfm(self):         
        self.state.toggle_amfm()     

    def scan(self):         
        self.state.scan()  


# Test our radio out
if __name__ == '__main__':
    radio = Radio() 
    actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 
    actions = actions * 2 

    for action in actions:     
        action()


builder

#!/usr/bin/python
# -*- coding : utf-8 -*-

"""
    @author: Diogenes Augusto Fernandes Herminio <diofeher@gmail.com>
    https://gist.github.com/420905#file_builder_python.py
"""


# Director
class Director(object):
    def __init__(self):
        self.builder = None

    def construct_building(self):
        self.builder.new_building()
        self.builder.build_floor()
        self.builder.build_size()

    def get_building(self):
        return self.builder.building


# Abstract Builder
class Builder(object):
    def __init__(self):
        self.building = None

    def new_building(self):
        self.building = Building()


# Concrete Builder
class BuilderHouse(Builder):
    def build_floor(self):
        self.building.floor = 'One'

    def build_size(self):
        self.building.size = 'Big'


class BuilderFlat(Builder):
    def build_floor(self):
        self.building.floor = 'More than One'
        
    def build_size(self):
        self.building.size = 'Small'


# Product
class Building(object):
    def __init__(self):
        self.floor = None
        self.size = None

    def __repr__(self):
        return 'Floor: %s | Size: %s' % (self.floor, self.size)


# Client
if __name__ == "__main__":
    director = Director()
    director.builder = BuilderHouse()
    director.construct_building()
    building = director.get_building()
    print(building)
    director.builder = BuilderFlat()
    director.construct_building()
    building = director.get_building()
    print(building)


graph_search

class GraphSearch:
    """Graph search emulation in python, from source
    http://www.python.org/doc/essays/graphs/"""

    def __init__(self, graph):
        self.graph = graph 
    
    def find_path(self, start, end, path=[]):
        self.start = start
        self.end = end
        self.path = path

        self.path += [self.start]
        if self.start == self.end:
            return self.path
        if not self.graph.has_key(self.start):
            return None
        for node in self.graph[self.start]:
            if node not in self.path:
                newpath = self.find_path(node, self.end, self.path)
                if newpath:
                    return newpath
        return None

    def find_all_path(self, start, end, path=[]):            
        self.start = start
        self.end = end
        self.path = path
        self.path += [self.start]
        if self.start == self.end:
            return [self.path]
        if not self.graph.has_key(self.start):
            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)
                for newpath in newpaths:
                    paths.append(newpath)                
        return paths

    def find_shortest_path(self, start, end, path=[]):         
        self.start = start
        self.end = end
        self.path = path
        
        self.path += [self.start]
        if self.start == self.end:
            return self.path
        if not self.graph.has_key(self.start):
            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 newpath:
                    if not shortest or len(newpath) < len(shortest):
                        shortest = newpath
        return shortest

#example of graph usage
graph = {'A': ['B', 'C'],
         'B': ['C', 'D'],
         'C': ['D'],
         'D': ['C'],
         'E': ['F'],
         'F': ['C']   
         }

#inistialization of new graph search object
graph1 = GraphSearch(graph)


print graph1.find_path('A', 'D')
print graph1.find_all_path('A', 'D')
print graph1.find_shortest_path('A', 'D')


flyweight

"""http://codesnipers.com/?q=python-flyweights"""

import weakref  


class Card(object):
    """The object pool. Has builtin reference counting"""
    _CardPool = weakref.WeakValueDictionary() 

    """Flyweight implementation. If the object exists in the
    pool just return it (instead of creating a new one)"""
    def __new__(cls, value, suit):         
        obj = Card._CardPool.get(value + suit, None)         
        if not obj:             
            obj = object.__new__(cls)             
            Card._CardPool[value + suit] = obj             
            obj.value, obj.suit = value, suit          
        return obj

    # def __init__(self, value, suit):         
    #     self.value, self.suit = value, suit      

    def __repr__(self):         
        return "<Card: %s%s>" % (self.value, self.suit)      


if __name__ == '__main__':
    # comment __new__ and uncomment __init__ to see the difference
    c1 = Card('9', 'h')
    c2 = Card('9', 'h')
    print(c1, c2)
    print(c1 == c2)
    print(id(c1), id(c2))


pool

"""http://stackoverflow.com/questions/1514120/python-implementation-of-the-object-pool-design-pattern"""


class QueueObject():
    def __init__(self, queue, auto_get=False):
        self._queue = queue
        self.object = self._queue.get() if auto_get else None

    def __enter__(self):
        if self.object is None:
            self.object = self._queue.get()
        return self.object

    def __exit__(self, type, value, traceback):
        if self.object is not None:
            self._queue.put(self.object)
            self.object = None

    def __del__(self):
        if self.object is not None:
            self._queue.put(self.object)
            self.object = None


def main():
    try:
        import queue
    except ImportError:  # python 2.x compatibility
        import Queue as queue

    def test_object(queue):
        queue_object = QueueObject(queue, True)
        print('Inside func: {}'.format(queue_object.object))

    sample_queue = queue.Queue()

    sample_queue.put('yam')
    with QueueObject(sample_queue) as obj:
        print('Inside with: {}'.format(obj))
    print('Outside with: {}'.format(sample_queue.get()))

    sample_queue.put('sam')
    test_object(sample_queue)
    print('Outside func: {}'.format(sample_queue.get()))

    if not sample_queue.empty():
        print(sample_queue.get())


if __name__ == '__main__':
    main()


composite

"""
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.

Created Anand B Pillai     <abpillai@gmail.com>

"""
__author__ = "Anand B Pillai"
__maintainer__ = "Anand B Pillai"
__version__ = "0.2"


def normalize(val):
    """ Normalize a string so that it can be used as an attribute
    to a Python object """
    
    if val.find('-') != -1:
        val = val.replace('-', '_')

    return val


def denormalize(val):
    """ De-normalize a string """

    if val.find('_') != -1:
        val = val.replace('_', '-')

    return val


class SpecialDict(dict):
    """ A dictionary type which allows direct attribute
    access to its keys """

    def __getattr__(self, name):

        if name in self.__dict__:
            return self.__dict__[name]
        elif name in self:
            return self.get(name)
        else:
            # Check for denormalized name
            name = denormalize(name)
            if name in self:
                return self.get(name)
            else:
                raise AttributeError('no attribute named %s' % name)

    def __setattr__(self, name, value):

        if name in self.__dict__:
            self.__dict__[name] = value
        elif name in self:
            self[name] = value
        else:
            # Check for denormalized name
            name2 = denormalize(name)
            if name2 in self:
                self[name2] = value
            else:
                # New attribute
                self[name] = value
        

class CompositeDict(SpecialDict):
    """ A class which works like a hierarchical dictionary.
    This class is based on the Composite design-pattern """

    ID = 0

    def __init__(self, name=''):

        if name:
            self._name = name
        else:
            self._name = ''.join(('id#', str(self.__class__.ID)))
            self.__class__.ID += 1

        self._children = []
        # Link  back to father
        self._father = None
        self[self._name] = SpecialDict()

    def __getattr__(self, name):

        if name in self.__dict__:
            return self.__dict__[name]
        elif name in self:
            return self.get(name)
        else:
            # Check for denormalized name
            name = denormalize(name)
            if name in self:
                return self.get(name)
            else:
                # Look in children list
                child = self.findChild(name)
                if child:
                    return child
                else:
                    attr = getattr(self[self._name], name)
                    if attr:
                        return attr
                    
                    raise AttributeError('no attribute named %s' % name)

    def isRoot(self):
        """ Return whether I am a root component or not """

        # If I don't have a parent, I am root
        return not self._father
    
    def isLeaf(self):
        """ Return whether I am a leaf component or not """

        # I am a leaf if I have no children
        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:
            return self._children.index(child)
        else:
            return -1

    def getDict(self):
        """ Return the contained dictionary """
        
        return self[self._name]

    def getProperty(self, child, 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' """

        # First get the child's dictionary
        childDict = self.getInfoDict(child)
        if childDict:
            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 = []
        for child in self._children:
            l.append(child)
            l.extend(child.getAllChildren())
            
        return l

    def getChild(self, name):
        """ Return the immediate child object with the given name """
        
        for child in self._children:
            if child.getName() == 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
        # any other children with similar names down the tree
        # is not considered.
        
        for child in self.getAllChildren():
            if child.getName() == 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
        # name, irrespective of the depth of look-up.
        
        children = []
        
        for child in self.getAllChildren():
            if child.getName() == name:
                children.append(child)

        return children
            
    def getPropertyDict(self):
        """ Return the property dictionary """
        
        d = self.getChild('__properties')
        if d:
            return d.getDict()
        else:
            return {}
        
    def getParent(self):
        """ Return the person who created me """

        return self._father
    
    def __setChildDict(self, child):
        """ Private method to set the dictionary of the child
        object 'child' in the internal dictionary """
        
        d = self[self._name]
        d[child.getName()] = child.getDict()

    def setParent(self, father):
        """ Set the parent object of myself """

        # This should be ideally called only once
        # by the father when creating the child :-)
        # though it is possible to change parenthood
        # when a new child is adopted in the place
        # of an existing one - in that case the existing
        # child is orphaned - see addChild and addChild2
        # methods !
        self._father = father
        
    def setName(self, name):
        """ Set the name of this ConfigInfo object to 'name' """        

        self._name = name

    def setDict(self, d):
        """ Set the contained dictionary """
        
        self[self._name] = d.copy()
        
    def setAttribute(self, name, value):
        """ Set a name value pair in the contained dictionary """
        
        self[self._name][name] = value

    def getAttribute(self, name):
        """ Return value of an attribute from the contained dictionary """
        
        return self[self._name][name]

    def addChild(self, name, force=False):
        """ Add a new child 'child' with the name 'name'.
        If the optional flag 'force' is set to True, the
        child object is overwritten if it is already there.

        This function returns the child object, whether
        new or existing """
        
        if type(name) != str:
            raise ValueError('Argument should be a string!')
        
        child = self.getChild(name)
        if child:
            # print 'Child %s present!' % name
            # Replace it if force==True
            if force:
                index = self.getIndex(child)
                if index != -1:
                    child = self.__class__(name)
                    self._children[index] = child
                    child.setParent(self)
                    
                    self.__setChildDict(child)
            return child
        else:
            child = self.__class__(name)
            child.setParent(self)
            
            self._children.append(child)
            self.__setChildDict(child)

            return child
        
    def addChild2(self, child):
        """ Add the child object 'child'. If it is already present,
        it is overwritten by default """
        
        currChild = self.getChild(child.getName())
        if currChild:
            index = self.getIndex(currChild)
            if index != -1:
                self._children[index] = child
                child.setParent(self)
                # Unset the existing child's parent
                currChild.setParent(None)
                del currChild
                
                self.__setChildDict(child)
        else:
            child.setParent(self)            
            self._children.append(child)
            self.__setChildDict(child)


if __name__ == "__main__":
    window = CompositeDict('Window')
    frame = window.addChild('Frame')
    tfield = frame.addChild('Text Field')
    tfield.setAttribute('size', '20')
    
    btn = frame.addChild('Button1')
    btn.setAttribute('label', 'Submit')

    btn = frame.addChild('Button2')
    btn.setAttribute('label', 'Browse')

    # print(window)
    # print(window.Frame)
    # print(window.Frame.Button1)
    # print(window.Frame.Button2)
    print(window.Frame.Button1.label)
    print(window.Frame.Button2.label)


strategy

"""http://stackoverflow.com/questions/963965/how-is-this-strategy-pattern-written-in-python-the-sample-in-wikipedia

In most of other languages Strategy pattern is implemented via creating some base strategy interface/abstract class and
subclassing it with a number of concrete strategies (as we can see at http://en.wikipedia.org/wiki/Strategy_pattern),
however Python supports higher-order functions and allows us to have only one class and inject functions into it's
instances, as shown in this example.
"""
import types


class StrategyExample:
    def __init__(self, func=None):
        self.name = 'Strategy Example 0'         
        if func is not None:
            self.execute = types.MethodType(func, self)      

    def execute(self):         
        print(self.name)   


def execute_replacement1(self):
    print(self.name + ' from execute 1')   


def execute_replacement2(self):
    print(self.name + ' from execute 2')  


if __name__ == '__main__':
    strat0 = StrategyExample()     

    strat1 = StrategyExample(execute_replacement1)
    strat1.name = 'Strategy Example 1'     

    strat2 = StrategyExample(execute_replacement2)
    strat2.name = 'Strategy Example 2'

    strat0.execute()
    strat1.execute()     
    strat2.execute()


proxy

import time 


class SalesManager:
    def work(self):                         
        print("Sales Manager working...")             

    def talk(self):                         
        print("Sales Manager ready to talk") 


class Proxy:
    def __init__(self):                         
        self.busy = 'No'                         
        self.sales = None             

    def work(self):
        print("Proxy checking for Sales Manager availability")                         
        if self.busy == 'No':                                      
            self.sales = SalesManager()                                      
            time.sleep(2)
            self.sales.talk()                         
        else:                                      
            time.sleep(2)
            print("Sales Manager is busy")


if __name__ == '__main__':
    p = Proxy()
    p.work()
    p.busy = 'Yes'
    p.work()


visitor

"""http://peter-hoffmann.com/2010/extrinsic-visitor-pattern-python-inheritance.html"""


class Node(object):
    pass


class A(Node):
    pass


class B(Node):
    pass


class C(A, B):
    pass


class Visitor(object):
    def visit(self, node, *args, **kwargs):
        meth = None
        for cls in node.__class__.__mro__:
            meth_name = 'visit_'+cls.__name__
            meth = getattr(self, meth_name, None)
            if meth:
                break

        if not meth:
            meth = self.generic_visit
        return meth(node, *args, **kwargs)

    def generic_visit(self, node, *args, **kwargs):
        print('generic_visit '+node.__class__.__name__)

    def visit_B(self, node, *args, **kwargs):
        print('visit_B '+node.__class__.__name__)


a = A()
b = B()
c = C()
visitor = Visitor()
visitor.visit(a)
visitor.visit(b)
visitor.visit(c)


顺序是乱的,因为爬虫是多线程的,反正内容都在这里。爬虫在我的Github里面,可以自己找。

最后还是强调一点,这些代码来自PythonTip,版权归PythonTip所有。

P.s 欢迎大家闲来无事一起刷题啊!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 外观模式(facade) 系统会随着演化变得非常复杂,最终形成大量的(并且有时是令人迷惑的)类和交互,这种情况并不...
    英武阅读 1,058评论 0 51
  • 抽象工厂 抽象工厂设计模式是抽象方法的一种泛化。概括来说,一个抽象工厂是(逻辑上的)一组工厂方法,其中的每个工厂方...
    英武阅读 5,284评论 0 52
  • 设计模式是什么?设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个...
    静熙老师哈哈哈阅读 553评论 0 7
  • 享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题。性能问题通常在资源受限的嵌入式系统中出现,比如智能...
    英武阅读 1,789评论 0 50
  • 工厂模式 创建型设计模式处理对象创建相关的问题,目标是当直接创建对象(在Python中是通过init()函数实现的...
    英武阅读 3,740评论 0 51