数据类和插槽导致值错误:`b` 在 `__slots__` 中与类变量冲突

huangapple go评论108阅读模式
英文:

Dataclasses and slots causing ValueError: 'b' in __slots__ conflicts with class variable

问题

我不理解错误消息,也找不到其他Stack Overflow的问题和答案,帮助我理解这个问题。MWE已在Python 3.9.2上测试过。我知道Python 3.10的dataclasses中有一个slots=True参数。但在这里不是一个选项。

错误输出:

Traceback (most recent call last):
  File "/home/user/dc.py", line 6, in <module>
    class Foo:
ValueError: 'b' in __slots__ conflicts with class variable

为什么会发生这种情况?我甚至不理解这个错误的背景。

#!/usr/bin/env pyhton3
from dataclasses import dataclass, field


@dataclass(init=False)
class Foo:
    __slots__ = ('a', 'b')
    a: int
    b: list[str] = field(init=False)

    def __init__(self, a, ccc):
        self.a = a

        # b = _some_fancy_modifications(ccc)

        self.b = b


if __name__ == '__main__':
    f = Foo(1, list('bar'))

成员b没有作为__init__()的参数给出,但是基于参数ccc计算得出。因此,我认为我需要编写自己的__init__()@dataclass(init=False))并且b成员不应该由dataclass初始化(field(init=False))。也许我在这里有什么误解?

英文:

I don't understand the error message and also couldn't find other SO questions and answers helping me to understand this. The MWE is tested with Python 3.9.2. I'm aware that there is a slots=True parameter in Pythons 3.10 dataclasses. But this isn't an option here.

The error output:

Traceback (most recent call last):
  File &quot;/home/user/dc.py&quot;, line 6, in &lt;module&gt;
    class Foo:
ValueError: &#39;b&#39; in __slots__ conflicts with class variable

Why does that happen? I even don't understand the background of that error.

#!/usr/bin/env pyhton3
from dataclasses import dataclass, field


@dataclass(init=False)
class Foo:
    __slots__ = (&#39;a&#39;, &#39;b&#39;)
    a: int
    b: list[str] = field(init=False)

    def __init__(self, a, ccc):
        self.a = a

        # b = _some_fancy_modifications(ccc)

        self.b = b


if __name__ == &#39;__main__&#39;:
    f = Foo(1, list(&#39;bar&#39;))

The member b is not given as an argument of __init__() but computed based on the argument ccc. Because of that I think I need to write my own __init__() (@dataclass(init=False)) and the b member shouldn't be initialized by dataclass (field(init=False)). Maybe I misunderstood something here?

答案1

得分: 1

为了使__slots__生效,Python必须在类字典中插入特殊的描述符对象来管理属性访问。否则,由于属性未存储在实例字典中,属性查找将完全无法找到您的属性。描述符告诉属性查找机制如何找到特殊属性。

为了使b槽起作用,Python必须插入一个描述符,该描述符对应于类字典中的'b'键。但是您已经在那里放了一些东西:您创建的field对象。您不能在同一个键的值为field对象和槽描述符。Python认识到这是一个问题,并引发错误以告诉您需要解决此问题。

这实际上不是您可以在您这一端修复的事情。数据类对__slots__的支持需要对数据类机制进行更改,这些更改发生在3.10中。在3.9中,您无法在数据类中使用槽。

英文:

For __slots__ to work, Python has to insert special descriptor objects into the class dict to manage attribute access. Otherwise, since the attributes aren't stored in the instance dict, attribute lookup would be completely unable to find your attributes. Descriptors tell the attribute lookup machinery how to find special attributes.

For the b slot to work, Python has to insert a descriptor for that attribute corresponding to the &#39;b&#39; key in your class dict. But you've already put something there: the field object you created. You can't have a field object and a slot descriptor as values for the same key. Python recognizes that this is a problem, and raises an error to tell you that you need to do something about this.

This isn't really something you can fix on your end. __slots__ support for dataclasses needs changes to the dataclass machinery, changes that happened in 3.10. In 3.9, you're stuck not using slots with dataclasses.

答案2

得分: -1

这与数据类无关。插槽被实现为内部类型“member_descriptor”的类变量。

尝试:

class Foo:
    __slots__ = ('a', 'b')

print(repr(Foo.a))
print(repr(Foo.a.__class__))

输出:

<member 'a' of 'Foo' objects>
<class 'member_descriptor'>
英文:

This is not related to dataclasses. A slot is realized as a class variable of an internal type "member_descriptor".

Try:

class Foo:
    __slots__ = (&#39;a&#39;, &#39;b&#39;)

print(repr(Foo.a))
print(repr(Foo.a.__class__))

Output:

&lt;member &#39;a&#39; of &#39;Foo&#39; objects&gt;
&lt;class &#39;member_descriptor&#39;&gt;

huangapple
  • 本文由 发表于 2023年3月12日 16:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75711922.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定