访问类内不存在的属性就会触发__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__
方法再返回类实例
,再触发__call__。即Chain().users
('michael')。
)(Chain().users
参考资料: