使用自定义 dict 类作为 Python 类的 __dict__ 属性的奇怪行为

发布于 2024-10-20 04:12:39 字数 1520 浏览 0 评论 0原文

我有一个从字典继承的类,以便添加一些自定义行为 - 在本例中,它将每个键和值传递给函数进行验证。在下面的示例中,“验证”只是打印一条消息。

对字典的分配按预期工作,每当将项目添加到字典时都会打印消息。但是,当我尝试使用自定义字典类型作为类的 __dict__ 属性时,属性赋值(反过来将键/值放入我的自定义字典类中)会以某种方式设法将值插入到字典中,同时完全绕过 __setitem__ (以及我定义的可能添加键的其他方法)。

自定义字典:

from collections import MutableMapping
class ValidatedDict(dict):
    """A dictionary that passes each value it ends up storing through
    a given validator function.
    """
    def __init__(self, validator, *args, **kwargs):
        self.__validator = validator
        self.update(*args, **kwargs)
    def __setitem__(self, key, value):
        self.__validator(value)
        self.__validator(key)
        dict.__setitem__(self, key, value)
    def copy(self): pass # snipped
    def fromkeys(validator, seq, v = None): pass # snipped
    setdefault = MutableMapping.setdefault
    update = MutableMapping.update

def Validator(i): print "Validating:", i

将其用作类的 __dict__ 属性会产生我不理解的行为。

>>> d = ValidatedDict(Validator)
>>> d["key"] = "value"
Validating: value
Validating: key
>>> class Foo(object): pass
... 
>>> foo = Foo()
>>> foo.__dict__ = ValidatedDict(Validator)
>>> type(foo.__dict__)
<class '__main__.ValidatedDict'>
>>> foo.bar = 100 # Yields no message!
>>> foo.__dict__['odd'] = 99
Validating: 99
Validating: odd
>>> foo.__dict__
{'odd': 99, 'bar': 100}

有人可以解释为什么它的行为不符合我的预期吗?它能或不能按照我尝试的方式工作吗?

I have a class that inherits from a dictionary in order to add some custom behavior - in this case it passes each key and value to a function for validation. In the example below, the 'validation' simply prints a message.

Assignment to the dictionary works as expected, printing messages whenever items are added to the dict. But when I try to use the custom dictionary type as the __dict__ attribute of a class, attribute assignments, which in turn puts keys/values into my custom dictionary class, somehow manages to insert values into the dictionary while completely bypassing __setitem__ (and the other methods I've defined that may add keys).

The custom dictionary:

from collections import MutableMapping
class ValidatedDict(dict):
    """A dictionary that passes each value it ends up storing through
    a given validator function.
    """
    def __init__(self, validator, *args, **kwargs):
        self.__validator = validator
        self.update(*args, **kwargs)
    def __setitem__(self, key, value):
        self.__validator(value)
        self.__validator(key)
        dict.__setitem__(self, key, value)
    def copy(self): pass # snipped
    def fromkeys(validator, seq, v = None): pass # snipped
    setdefault = MutableMapping.setdefault
    update = MutableMapping.update

def Validator(i): print "Validating:", i

Using it as the __dict__ attribute of a class yields behavior I don't understand.

>>> d = ValidatedDict(Validator)
>>> d["key"] = "value"
Validating: value
Validating: key
>>> class Foo(object): pass
... 
>>> foo = Foo()
>>> foo.__dict__ = ValidatedDict(Validator)
>>> type(foo.__dict__)
<class '__main__.ValidatedDict'>
>>> foo.bar = 100 # Yields no message!
>>> foo.__dict__['odd'] = 99
Validating: 99
Validating: odd
>>> foo.__dict__
{'odd': 99, 'bar': 100}

Can someone explain why it doesn't behave the way I expect? Can it or can't it work the way I'm attempting?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别靠近我心 2024-10-27 04:12:39

这是一个优化。为了支持 __dict__ 上的元方法,每个实例分配都需要检查元方法是否存在。这是一个基本操作——每个属性查找和赋值——因此检查这一点所需的额外几个分支将成为整个语言的开销,对于与 obj.__getattr__ 或多或少冗余的东西和obj.__setattr__

This is an optimization. To support metamethods on __dict__, every single instance assignment would need to check the existance of the metamethod. This is a fundamental operation--every attribute lookup and assignment--so the extra couple branches needed to check this would become overhead for the whole language, for something that's more or less redundant with obj.__getattr__ and obj.__setattr__.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文