zoukankan      html  css  js  c++  java
  • 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()
    
  • 相关阅读:
    hdu 5072 Coprime (容斥)
    洛谷 P1411 树 (树形dp)
    Tr/ee AtCoder
    sys.path
    uname
    sys.platform
    Eclipse Basic
    Eclipse Color Theme
    Pydev
    scons
  • 原文地址:https://www.cnblogs.com/tomyyyyy/p/12800224.html
Copyright © 2011-2022 走看看