今天简单聊聊python的设计模式,GOF设计模式(c++)和Head first design pattern(Java)是两本设计模式的经典,基本可以照搬在python上面,但是你会发现python有很多它特有的东西,比如它并没有多个构造函数,相对应的它有classmethod,所以python设计模式还是有值得聊聊的地方。
构造函数:
python2:
class Person(object): def __init__(self, name): self.name = name
python3:
class Person: def __init__(self, name): self.name = name
调用的时候不需要用new,person = Person("xiaozhang")。所有的class都从object继承,python2需要显式而python3都帮你弄好了。继承与object有很多好处,一个好处就是super()。python3 可以直接通过super().parent_method()调用父类的方法而python2需要super(子类名字,self).parent_method()
继承
class Animal: def __init__(self, name): self.name = name class Dog(Animal): pass class Cat(Animal): pass
>>> animal = Dog("dodo") >>> animal.name 'dodo' >>> isinstance(animal, Animal) True >>> isinstance(animal, Dog) True >>> isinstance(animal, Cat) False
isinstance 可以用来check object types。
Override
>>> class Animal: ... sound = "" ... def speak(self): ... print("The animal says: " + self.sound) ... >>> class Dog(Animal): ... sound = "WangWang!" ... >>> class Cat(Animal): ... sound = "MiaoMiao" ... >>> class Turtle(Animal): ... pass ... >>> Dog().speak() The animal says: WangWang! >>> Cat().speak() The animal says: MiaoMiao >>> Turtle().speak() The animal says:
python不支持方法重载,有些语言比如c++,java可以定义多个同名函数只要参数类型不同即可,python则不可以,后面定义的会覆盖前面定义的方法如果有多个同名方法。
私有类型
python没有访问控制,习惯是用self._something表示这东西是私有的请不要直接获取它,然而你可以随便拿。
你也可以使用__,python会mangle这个变量__something为_classname__something,如果知道这层name mangling你还是可以获取它。
设计模式之read only
python有一个decorator叫做property,加了property的方法,只能读,不能写。如果你想写,要额外加被decorate的方法名.setter。setter里可以做一些input check。有了property我们就可以创造性的refactor一些类。
设计模式之pub-sub
import os import time class FileWatcher(object): def __init__(self, path_of_file_to_watch): self.path = path_of_file_to_watch self.observers = set() def register(self, name): self.observers.add(name) def unregister(self, name): self.observers.discard(name) def notify(self, message): for i in self.observers: i.update(message) class FileObserver(object): def __init__(self, name): self.name = name def update(self, message): print "%s noticed that the file is now %d bytes" % (self.name, message) filename = "/tmp/test.txt" f = FileWatcher(filename) bob = FileObserver("bob") john = FileObserver("john") stacy = FileObserver("stacy") f.register(bob) f.register(john) f.register(stacy) init_size = os.stat(filename).st_size while True: if os.stat(filename).st_size != init_size: f.notify(os.stat(filename).st_size) init_size = os.stat(filename).st_size time.sleep(1)
classmethod模式
def __init__(self, something): *** @classmethod def some_alternative_constructor(cls, some_other_thing): *** something = some_other_thing balbla return cls(something)
调用的时候直接用类名.另一个构造函数,返回需要的对象。直接适用于子类。
staticmethod
相当于定义函数,不用加self 啦,cls啦,相当于直接写function,然后可以用类名直接调用。