dictproxy的目的是什么?
一个类型的 __dict__
是一个只读的 dictproxy
对象。我想知道它的目的是什么。难道只是为了“禁止修改内置类型”吗?我发现有一种方法可以绕过这个限制。我知道修改内置类型不是个好主意,但我正在尝试动态修改 Cython 的 cdef class
。
我想知道以这种方式修改 cdef class
的 __dict__
是否有危险?
这里是代码:
import gc
gc.get_referents(float.__dict__)[0]["square"] = lambda self: self*self
(3.14).square()
2 个回答
__dict__
是一个命名空间对象,用来存放类的属性。
只要你不修改 __dict__
本身,修改这个字典对象应该没有问题:
举个例子:
//good
MyClass.x = 1
//bad
MyClass.__dict__['x'] = 1
//good
m = MyClass()
m.x = 1
//also good
m.__dict__['x'] = 1
根据Python的文档 [ 链接 ]:
给属性赋值会更新模块的命名空间字典,比如,m.x = 1 相当于 m.__dict__["x"] = 1。
所以,修改 dict 的对象应该没有问题。
此外:
因为我们可以修改类的属性,所以类的字典总是可以写的:
__dict__ | 支持任意函数属性的命名空间。 | 可写
注意
可能CPython的实现和Python有些不同,但根据我从文档中看到的,并没有提到这一点。
dictproxy
的主要作用是在类中使用,它可以帮助Python解释器进行一些优化,并确保其稳定性。具体的优化要求可以参考MartijnPieters的评论,主要是因为类的属性名(即class.__dict__
中的键)必须始终是字符串。
dictproxy
还可以防止解释器出现某些不稳定的情况。关于这种不稳定性,可以查看python.org上讨论的一个错误报告和修复,标题是绕过 __dict__ 的只读性。如果不使用某种代理机制,__dict__
是可以被写入的。如果可以写入,就可以被删除。在这个错误报告中,他们讨论了一些情况下__dict__
被删除后导致解释器崩溃的情况。
需要注意的是,这和类的实例是不同的,类的实例是可以直接赋值的,或者使用__setitem__()
来赋值:
instance.__dict__['x'] = 1
另外,实例的__dict__
也是可以被删除的。如果被删除了,当你尝试给属性赋值时,它会自动重新创建:
del instance.__dict__
instance.a = 1
instance.__dict__
总结
总的来说,dictproxy
让类的操作更加高效,同时也让解释器更加稳定。