这是在阅读廖雪峰老师的Python教程时遇到的问题
定制类
文章中提出来如何创建一个链式调用:
class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
return Chain('%s/%s' % (self._path, path))
def __str__(self):
return self._path
__repr__ = __str__
结果为
>>> Chain().status.user.timeline.list
'/status/user/timeline/list'
对其原因的解释在评论区可以找到:
首先定义了Chain类,init函数接收一个path变量。
然后getattr函数,这个函数是如果你使用了类没有定义的变量的时候,就会调用它。它返回一个Chain(),并且把“原本的path/没有定义的变量”作为path的值传入了Chain里
call函数就是将类当作类似函数一样调用
str函数是当有打印函数是,就会调用这个
所以这段代码的执行流程为:
先是Chain()创建了一个实例,最开始的path默认为“”,然后.a,因为没有a这个变量,所以会调用getattr函数,返回一个Chain实例,然后把/a作为path传入,继续.b,因为没有b变量,所以执行getattr函数,将/a/b作为path传入,然后.user(“ChenTian”),先会执行getattr返回Chain实例,但是因为有()括号在,所以返回的是Chain(),这个就会调用call函数了,然后把“ChenTian”作为path传入,然后call函数就返回了/a/b/user/ChenTian,剩下的类同。
主要是user(“ChenTian”)这一句,我的理解是,先执行了getattr,然后执行call,并把ChenTian作为path传入
具体的细节我目前不是很清楚,我猜测是多了括号所以会调用call,不过不知道为什么。。。
按照这个说法,我做了一个实验:
class Chain(object):
def __init__(self, path='initial'):
self._path = path
def __getattr__(self, path):
return Chain('!%s@%s' %(self._path, path))
def __str__(self):
return self._path
__repr__ = __str__
结果却是
from temp import Chain
Chain().status.user.timeline.list
Out[68]: !!!!initial@status@user@timeline@list
希望大神帮忙解答,为什么前面有连续的 ‘!’ 出现