Python 魔术方法小结
Python 魔术方法小结
_ _ init __
实例化对象时调用
class Foo: def init(self,name): self.name = name f = Foo(‘CharmNight‘) # 这时候就调用init方法
_ _ new__
创建类对象时调用
_ _ new__ ()方法始终都是 类的静态方法,即使没有被加上静态方法装饰器
class Foo: def new(cls,*args,**kwargs): return super().new(cls) def init(self): pass f = Foo() __new()__ 方法创建对象,在init()方法之前被调用,返回一个self对象,并将该对象传给init()的第一个参数。一般不需要复写new()方法,如果有需求:例如 单例模式可以通过重写new方法 或者在类创建时进行一些修改
单例模式
当然单例模式不止这一种写法,有很多方法都可以实现单例
# 通过__new__()方法实现单例模式 class Foo: _instance = None def __new__(cls, *args, **kwargs): if not hasattr(Foo,‘_instance‘): cls._instance = super().__new__(cls) return cls._instance
__ call__
Python中的函数是一级对象。这意味着Python中的函数的引用可以作为输入传递到其他的函数/方法中,并在其中被执行。
而Python中类的实例(对象)可以被当做函数对待。也就是说,我们可以将它们作为输入传递到其他的函数/方法中并调用他们,正如我们调用一个正常的函数那样。而类中__call()__
函数的意义正在于此。为了将一个类实例当做函数调用,我们需要在类中实现__call()__
方法。也就是我们要在类中实现如下方法:def __call__(self, [args...])
。这个方法接受一定数量的变量作为输入。__call()__
的作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期(__call()__
不影响一个实例的构造和析构)。但是__call()__
可以用来改变实例的内部成员的值
说人话就是__call__
方法就是 让对象加括号 执行call里的内容。
class Foo: def __init__(self, name): self.name = name def __call__(self, *args, **kwargs): self.name = self.name.upper() f = Foo(‘Charm_Night‘) f() print(f.name)
__ getattr__
拦截点号运算。当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法
class Foo(): def __init__(self, item): self.item = item def __getattr__(self, item): print(‘Run getattr‘) return item f = Foo([1,2,3]) print(f.name)
Run getattr name
哈?说没看懂什么时候调用? 简单说就是当调用该属性却没有找到时,就会执行_ _ getattr _ _方法
如果属性查找(attribute lookup)在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, 如果没有定义这个函数,那么抛出AttributeError异常。由此可见,__getattr__一定是作用于属性查找的最后一步,兜底
_ _ getattr _ _ 使得实现adapter wrapper模式非常容易,我们都知道“组合优于继承”,_ _ getattr __实现的adapter就是以组合的形式。
eg:
_ _ getattr _ _ 使得实现adapter wrapper模式非常容易,我们都知道“组合优于继承”,_ _ getattr __实现的adapter就是以组合的形式。
class adaptee(object): def foo(self): print( ‘foo in adaptee‘) def bar(self): print (‘bar in adaptee‘) class adapter(object): def __init__(self): self.adaptee = adaptee() def foo(self): print(‘foo in adapter‘) self.adaptee.foo() def __getattr__(self, name): print(‘run‘) return getattr(self.adaptee, name) if __name__ == ‘__main__‘: a = adapter() a.foo() a.bar()
foo in adapter foo in adaptee bar in adaptee
_ _ getattribute__
_ _ getattribute__是访问属性的方法,我们可以通过方法重写来扩展方法的功能。
对于python来说,属性或者函数都可以被理解成一个属性,且可以通过_ _ getattribute__获取。
当获取属性时,直接return object._ getattribute_(self,item) 或者使用 super(). _ _ getattribute _ _(item)
class Foo: def __init__(self): self.name = ‘Night‘ def __getattribute__(self, item): print(‘Run getattribute‘) if item is ‘func‘: return super().__getattribute__(‘func‘) elif item is ‘name‘: return super().__getattribute__(‘name‘) else: return super().__getattribute__(‘demo‘) def demo(self): print(‘Run demo‘) def func(self): print(‘Run func‘) f = Foo() print(f.name) f.func() f.a()