将 python 数据类和属性一起使用真的存在错误吗?

发布于 2025-01-17 21:06:41 字数 2888 浏览 1 评论 0原文

我曾经在这里:

和无法找到为什么这个简单的代码工作正常的直接答案...

class Vehicle:
    
    def __init__(self, wheels: int = 10):
        self.wheels = wheels # -> calls the setter method
    
    @property
    def wheels(self) -> int:
        print("getting wheels")
        return self._wheels
    
    @wheels.setter
    def wheels(self, wheels: int):
        print("setting wheels to", wheels)
        self._wheels = wheels

v = Vehicle() 
number = v.wheels # -> calls the getter method
print(number)

# last output: 10

...但是这个却不能(使用 dataclass):

from dataclasses import dataclass

@dataclass
class Vehicle:
    
    wheels: int = 10
    
    @property
    def wheels(self) -> int:
        print("getting wheels")
        return self._wheels
    
    @wheels.setter
    def wheels(self, wheels: int):
        print("setting wheels to", wheels)
        self._wheels = wheels

v = Vehicle() 
number = v.wheels
print(number)

# output: <property object at 0x000002042D70DDB0>

即使当 dataclass 的官方文档 在开头就明确指出装饰器 @dataclass 准确地添加了第一个代码中的 __init__ 方法,即这段代码:

@dataclass
class Vehicle:
    wheels: int = 10

应该添加这个 __init__:

def __init__(self, wheels: int = 10):
    self.wheels = wheels

这真的是一个错误吗?


简短说明:

私有属性 _wheels 只能在 property 的方法内部访问,正如它应该的那样(以隔离它)。

我在其他线程(上面列出)中发现该属性是在方法外部操作的,公开为“公共”,这在某些情况下是不需要的。

I have been here:

and could not find a direct answer to why this simple code works fine...

class Vehicle:
    
    def __init__(self, wheels: int = 10):
        self.wheels = wheels # -> calls the setter method
    
    @property
    def wheels(self) -> int:
        print("getting wheels")
        return self._wheels
    
    @wheels.setter
    def wheels(self, wheels: int):
        print("setting wheels to", wheels)
        self._wheels = wheels

v = Vehicle() 
number = v.wheels # -> calls the getter method
print(number)

# last output: 10

...but this one does not (using dataclass):

from dataclasses import dataclass

@dataclass
class Vehicle:
    
    wheels: int = 10
    
    @property
    def wheels(self) -> int:
        print("getting wheels")
        return self._wheels
    
    @wheels.setter
    def wheels(self, wheels: int):
        print("setting wheels to", wheels)
        self._wheels = wheels

v = Vehicle() 
number = v.wheels
print(number)

# output: <property object at 0x000002042D70DDB0>

even when the official documentation of dataclass tells explicitly in the beginning that the decorator @dataclass adds exactly the __init__ method from the first code, i.e., this code:

@dataclass
class Vehicle:
    wheels: int = 10

should add this __init__:

def __init__(self, wheels: int = 10):
    self.wheels = wheels

Is that really a bug?


Short Note:

The private attribute _wheels is accessed only inside the property's methods, as it should be (to isolate it).

I found in others threads (listed above) that this attribute is manipulated outside the methods, exposed as 'public', which is not desired in some cases.

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

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

发布评论

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

评论(1

迷你仙 2025-01-24 21:06:41

这是你的代码中的一个错误。

此代码:

wheels: int = 10

wheels 设置为 10,然后紧接着此代码:

@property
def wheels(self) -> int:
    print("getting wheels")
    return self._wheels

wheels 设置为 property 实例。

@dataclass 看不到10。你的 10 不见了。注释仍然存在,因此 @dataclass 创建一个 wheels 字段,但字段的默认值是 property 实例,而不是 10代码>.

That's a bug in your code.

This code:

wheels: int = 10

sets wheels to 10, then this code immediately after:

@property
def wheels(self) -> int:
    print("getting wheels")
    return self._wheels

sets wheels to a property instance.

@dataclass can't see the 10. Your 10 is gone. The annotation remains, so @dataclass creates a wheels field, but your field's default value is a property instance, not 10.

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