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(‘\users\michael‘),再一次重建实例,覆盖掉Chain(‘\users‘), #记 renew = Chain(‘\users\michael‘), 此时新实例的属性renew.__path = \users\michael; Step 4: Chain().users(‘michael‘).repos # 这一步是查询renew实例的属性repos,由于没有这一属性,就会执行__getattr__()函数,再一次返回新的实例Chain(‘\users\michael\repos‘)并且覆盖点之前的实例, # 这里记 trinew =Chain(‘\users\michael\repos‘),不要忘了,一单定义了一个新的实例,就会执行__init__方法; Step 5: print(Chain().users(‘michael‘).repos) = print(trinew) #由于我们定义了__str__()方法,那么打印的时候就会调用此方法,据此方法的定义,打印回来的是trinew的__path属#性,即——\users\michael\repos 。至此,我们也把所有定义的有特殊用的方法都用上了,完毕。 廖雪峰教程下某个优秀的解释
相关推荐
taiyangshenniao 2020-10-05
flycony 2020-09-23
jacktangj 2020-09-18
YENCSDN 2020-09-15
夜斗不是神 2020-11-17
huavhuahua 2020-11-20
Yasin 2020-11-16
xiaoseyihe 2020-11-16
千锋 2020-11-15
diyanpython 2020-11-12
chunjiekid 2020-11-10
wordmhg 2020-11-06
世事一场大梦 2020-11-17
xiaoseyihe 2020-11-16
Morelia 2020-11-03
CloudXli 2020-11-03
文山羊 2020-10-31
comtop0 2020-10-31
pythonxuexi 2020-10-30