Python对象里的 __call__ 和 __getattr__
Posted iamdaguduizhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python对象里的 __call__ 和 __getattr__相关的知识,希望对你有一定的参考价值。
class Chain(object):
def __init__(self, path=‘‘):
print("=", path)
self._path = path
def __getattr__(self, path):
print(path, type(path))
return Chain(‘%s/%s‘ % (self._path, path))
def __call__(self, value):
print(‘My name is %s.‘ % value)
return Chain(‘%s/%s‘ % (self._path, ‘:‘ + value))
def __str__(self):
return self._path
__repr__ = __str__
# print(Chain().status.user.timeline.list)
# 执行结果Chain().status = Chain(‘status‘)
# GET /users/:user/repos
# 调用时,需要把:user替换为实际用户名。如果我们能写出这样的链式调用:
#
print(Chain().users (‘michael‘).repd)
(‘=‘, ‘‘)
(‘users‘, <type ‘str‘>)
(‘=‘, ‘/users‘)
My name is michael.
(‘=‘, ‘/users/:michael‘)
(‘repd‘, <type ‘str‘>)
(‘=‘, ‘/users/:michael/repd‘)
/users/:michael/repd
定义__call__会再函数调用的时候执行。 getattr 会再调用实例某个不存在的属性是执行。
Step 1:
Chain() # 实例化
Step 2:
Chain().users
# 由于没有给实例传入初始化对应属性的具体信息,从而自动调用__getattr__()函数,从而有:
Chain().users = Chain(‘users‘) # 这是重建实例
Step 3:
Chain().users(‘michael‘)
Chain().users(‘michael‘) = Chain(‘users‘)(‘michael‘) # 这是对实例直接调用,相当于调用普通函数一样
# 关键就在这步,上面的朋友没有说明晰(并不是说你们不懂),这一步返回的是Chain(‘usersmichael‘),再一次重建实例,覆盖掉Chain(‘users‘),
#记 renew = Chain(‘usersmichael‘), 此时新实例的属性renew.__path = usersmichael;
Step 4:
Chain().users(‘michael‘).repos
# 这一步是查询renew实例的属性repos,由于没有这一属性,就会执行__getattr__()函数,再一次返回新的实例Chain(‘usersmichael
epos‘)并且覆盖点之前的实例,
# 这里记 trinew =Chain(‘usersmichael
epos‘),不要忘了,一单定义了一个新的实例,就会执行__init__方法;
Step 5:
print(Chain().users(‘michael‘).repos) = print(trinew) #由于我们定义了__str__()方法,那么打印的时候就会调用此方法,据此方法的定义,打印回来的是trinew的__path属#性,即——usersmichael
epos 。至此,我们也把所有定义的有特殊用的方法都用上了,完毕。
廖雪峰教程下某个优秀的解释
以上是关于Python对象里的 __call__ 和 __getattr__的主要内容,如果未能解决你的问题,请参考以下文章
python __del__方法(析构函数)和垃圾回收机制__call__方法和可调用对象