Python 魔术方法小结

Posted tomyyyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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()

以上是关于Python 魔术方法小结的主要内容,如果未能解决你的问题,请参考以下文章

Python 魔术方法笔记

PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结

Python:不应该使用的魔术方法

怎么让你的Python代码更优雅!

PHP链式操作通过call和callstatic魔术方法的实现,以及phpstorm通过注释去追踪function

PHP链式操作通过call和callstatic魔术方法的实现,以及phpstorm通过注释去追踪function