这篇文章讨论下面两个问题:
1:getattr(),setattr()它是用于解决什么问题的,它的应用场景是什么?背后的设计思想是什么?
2:a._dict_,以及dir(a)的区别是?
先说第一个,
var = ‘fun’
getattr(obj, var),这种写法相比obj.fun,它有哪些优点呢?在下面几种情况下用getattr(),setattr():
1:你不知道对象的属性名的时候,比如你要向对象所有的属性添加值。
for key, value in dict.items():
setattr(obj, key, value)
上面是对对象所有属性赋值,你不需要知道每个属性值。也更适合批量化操作。
2:想象一下,你要调用一个类里的某一批方法,这些方法是以test开头的。你怎么办?
a = A():
list = a.__dict__.keys() #拿到秘有属性的列表
#现在从里面找出以test开头的。
test_list = [item form item in list if item.startwith('test')
for fun in test_list:
getattr(obj, fun)
#其实单元测试模块就用到这个。
背后的设计思想:
上面说了应用场景,那么它背后的设计思想是什么呢?其实还是用到抽象,封装的思想。我们熟悉用函数名来封装一个函数体过程。只不过,这里的getattr是用一个变量来封闭具体的值。这也是“面向抽象,而不是实现编程”的一种应用。如果是obj.fun,这是实现,把代码写死了,而写var = input(), get(obj, var),这代码就有可扩展性,把变化封装在变量的定义中。我个人觉得,这也是一种响应式编程的思想,具体调用哪个方法,是根据字符的不同而不同的。所以可以叫做基于字符的响应式编程思想。我自己编的。
下面说开头提出的第二个问题:
a._dict_,它只是列出当前实例的属性,而dir(a),它是一个内置的函数,会把实例,以及它的类,父类,所以祖先的属性全部列出。
当我们写a.x,还是getattr(obj,‘x’),解释器先去a.__dict__实例属性字典里找,找不到就去类的属性字典,然后父类,超类…,所有祖先过一遍。