如何处理Python查找:创建一个点分隔的名称并使用它直到销毁 = 777
我刚开始学Python,对Python的点名查找过程特别感兴趣,想要试试。请问我该如何在“make.py”里写一个类或函数,让这些赋值语句能够成功运行呢?
import make
make.a.dot.separated.name = 666
make.something.else.up = 123
make.anything.i.want = 777
1 个回答
#!/usr/bin/env python
class Make:
def __getattr__(self, name):
self.__dict__[name] = Make()
return self.__dict__[name]
make = Make()
make.a.dot.separated.name = 666
make.anything.i.want = 777
print make.a.dot.separated.name
print make.anything.i.want
当找不到某个命名的值时,会调用这个特别的 __getattr__
方法。比如说,写 make.anything.i.want
其实就相当于:
m1 = make.anything # calls make.__getattr__("anything")
m2 = m1.i # calls m1.__getattr__("i")
m2.want = 777
上面的实现通过调用 __getattr__
方法,创建了一系列的 Make
对象,每当访问一个未知的属性时,就会这样做。这让我们可以把点号访问嵌套得很深,直到最后赋值的时候,才会真正给这个属性一个值。
Python 文档 - 自定义属性访问:
object.__getattr__(self, name)
当在常规地方找不到某个属性时,就会调用这个方法(也就是说,这个属性既不是实例属性,也不在
self
的类树中)。name
是属性的名字。这个方法应该返回计算出来的属性值,或者抛出一个AttributeError
异常。要注意,如果通过正常的方式找到了这个属性,就不会调用
__getattr__()
。这是__getattr__()
和__setattr__()
之间故意设计的不对称。这么做是为了提高效率,同时也因为如果不这样的话,__getattr__()
就没有办法访问实例的其他属性。值得一提的是,至少对于实例变量来说,你可以通过不在实例属性字典中插入任何值(而是插入到另一个对象中)来假装拥有完全的控制权。想要在新式类中真正实现完全控制,可以参考下面的__getattribute__()
方法。
object.__setattr__(self, name, value)
当尝试给某个属性赋值时,就会调用这个方法。这个方法会替代正常的机制(也就是说,把值存储在实例字典中)。
name
是属性的名字,value
是要赋给它的值。如果
__setattr__()
想要给实例属性赋值,它不应该直接执行self.name = value
—— 这样会导致递归调用自己。相反,它应该把值插入到实例属性的字典中,比如self.__dict__[name] = value
。对于新式类来说,应该调用同名的基类方法,而不是直接访问实例字典,例如object.__setattr__(self, name, value)
。