#第一步,初始化Student类, 利用__getattr__将新增属性名称更新至默认属性的取值中,这样就实现了利用新属性的名称(实际上没有新建属性)更新原属性的取值
class Student(object):
def __init__(self, name=''): #默认name输入值为空,此处name并不是真正的属性,只是输入变量;真正的属性real_name按照name值更新
self.real_name = name #真正的属性名称为real_name,真正的属性名称是跟随着self.后出现的变量名称
def __getattr__(self, attr): #通过__getattr__功能判断输入的attr变量名称是否和已有属性(real_name)一样,如果不一样则运行下面语句
if attr.startswith('_'): #解决‘_ipython_canary_method_should_not_exist_’问题,可忽略
raise AttributeError(attr) #解决‘_ipython_canary_method_should_not_exist_’问题,可忽略
return Student(self.real_name + ' and ' + attr) #如果attr为新属性名称则返回一个Student()实例,这个实例中的输入变量name按照()内的内容设置
Student() #输出<__main__.Student at 0x地址>,新建了一个实例
Student().real_name #输出'', 返回该实例的属性real_name的数值
Student().A #输出<__main__.Student at 0x地址>,说明输出的仍然是1个实例,这个实例其实就是Student(''+' and '+'A')
Student().A.real_name #输出' and A',返回实例Student(''+' and '+'A')的属性real_name的数值
Student().A.B #输出<__main__.Student at 0x地址>,说明输出的是1个实例,这个实例其实就是Student(Student(' and A' and '+'B'))
Student().A.B.real_name #输出' and A and B',返回实例Student(Student(' and A' and '+'B'))的属性real_name的数值
#第二步,通过print()看一下中间过程发生了什么
class Student(object):
def __init__(self, name=''):
self.real_name = name
print('Students Names are: %s' % self.real_name) #通过打印来看一下每一步生成的real_name属性值
def __getattr__(self, attr):
if attr.startswith('_'): #解决‘_ipython_canary_method_should_not_exist_’问题,可忽略
raise AttributeError(attr) #解决‘_ipython_canary_method_should_not_exist_’问题,可忽略
return Student(self.real_name + ' and ' + attr)
Student().A.B
#输出为4行结果
# Students Names are: #这一行是运行Student()后打印属性real_name的结果
# Students Names are: and A #这一行是运行Student(''+' and '+'A')后打印属性real_name的结果
# Students Names are: and A and B #这一行是运行Student(Student(' and A' and '+'B'))后打印属性real_name的结果
# Out[1]: <__main__.Student at 0x地址> #Student().A.B输出结果为实例
#第三步,为了让<__main__.Student at 0x地址>变为属性real_name的数值,需要增加__repr__功能
class Student(object):
def __init__(self, name=''):
self.real_name = name
def __getattr__(self, attr):
return Student(self.real_name + ' and ' + attr)
def __repr__(self): #将内部打印结果变为下面的输出内容
return self.real_name #输出属性real_name的数值
Student().A #因为__repr__替换了内部打印,可以直接输出结果' and A'
Student().A.B #因为__repr__替换了内部打印,可以直接输出结果' and A and B'
采蘑菇的lucas_688
以类Student为例,再更新为Chain