python __getattr__ 与 __call__

来源:互联网 发布:ubuntu系统字体 编辑:程序博客网 时间:2024/06/06 01:44

访问类内不存在的属性就会触发__getattr__方法(前提你实现该方法)

类自己也可以作为一个方法调用,通过实现__call__

如:

class A():    def __init__(self):        pass    def __call__(self):        print('A!')>>> A()()A!

__str__ 是作为输出字符串时的触发方法

__repr__为调试时的输出,一般这样写:

def __str__(self):        return self.__path    __repr__ = __str__

看一个例子。

>>> class Chain(object):    def __init__(self, path = ''):        self.__path = path        return    def __call__(self, name):        return Chain('%s/%s' % (self.__path, name))    def __str__(self):        return self.__path    __repr__ = __str__    def __getattr__(self, path):        return Chain('%s/%s' % (self.__path, path))>>> Chain().users('michael').repos/users/michael/repos>>> Chain().users('michael').users.repos/users/michael/users/repos

第二个输入

这里Chain().users('michael')部分,首先代码没有定义users()方法(如果有定义方法,它的优先级高与__getattr__),所以这么把它看做未定义属性。于是触发__getattr__。__getattr__(self,path)返回Chain('/users'),相当于变成了Chain('/users')('michael').users.repos.Chain('/users')('michael')触发__call__,得到Chain('/users/michael/')。users.repos。再后面同理。最后得到Chain('/users/michael/users/repos')。通过__repr__输出。

如果是print(Chain('/users/michael/users/repos') )  则通过__str__输出。

主要Chain().users('michael')有歧义,可以把users('michael')看成方法调用(如果有定义,则优先考虑),如果没有定义也可以看成Chain().users为属性,触发__getattr____getattr__方法再返回类实例Chain().users,再触发__call__。即(Chain().users)('michael')。

参考资料:

http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319098638265527beb24f7840aa97de564ccc7f20f6000#0

0 0