标签: python-dataclasses

为什么 dataclasses.astuple 返回类属性的深层副本?

在下面的代码中,该astuple函数正在执行数据类的类属性的深层复制。为什么它产生的结果与函数不同my_tuple

import copy
import dataclasses


@dataclasses.dataclass
class Demo:
    a_number: int
    a_bool: bool
    classy: 'YOhY'

    def my_tuple(self):
        return self.a_number, self.a_bool, self.classy

class YOhY:
    def __repr__(self):
        return (self.__class__.__qualname__ + f" id={id(self)}")


why = YOhY()
print(why)  # YOhY id=4369078368

demo = Demo(1, True, why)
print(demo)  # Demo(a_number=1, a_bool=True, classy=YOhY id=4369078368)

untrupled = demo.my_tuple()
print(untrupled)  # YOhY id=4369078368

trupled = dataclasses.astuple(demo)
print(trupled)  # YOhY id=4374460064

trupled2 = trupled
print(trupled2)  # YOhY id=4374460064

trupled3 = copy.copy(trupled)
print(trupled3)  # YOhY id=4374460064

trupled4 …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

6
推荐指数
1
解决办法
2225
查看次数

在 Cython 中使用数据类

我正在使用 cython 进行代码混淆,因此目前性能不是问题。问题在于使用数据类。

cythonize 包含数据类定义的代码时,在编译期间没有错误。但是在运行代码时,我得到一个TypeError: <field> is a field but has no type annotation.

这是我试图 cythonize 的代码:

from dataclasses import dataclass, field
from typing import Dict, Any, List

@dataclass
class dataclass_test:
    ddict: Dict[str, Any]
    sstr: str
    bbool: bool
    llist: List[str]
    ffloat: float
    llist1: List[str] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)

在没有 cythonization 的情况下运行代码工作正常。但是在 cythonization 之后,我收到以下错误消息:

 File "dataclass_.py", line 4, in init dataclass_
    @dataclass   File "/home/aryskin/miniconda3/envs/tf113_gpu_conda/lib/python3.7/dataclasses.py", line 991, in dataclass
    return wrap(_cls)   File "/home/aryskin/miniconda3/envs/tf113_gpu_conda/lib/python3.7/dataclasses.py", line 983, in wrap
    return _process_class(cls, init, repr, eq, order, …
Run Code Online (Sandbox Code Playgroud)

python cython python-dataclasses

6
推荐指数
1
解决办法
626
查看次数

解析 JSON 对象时保留字作为数据类中的属性名称

我在处理 ETL 管道时偶然发现了一个问题。我正在使用数据类dataclass来解析 JSON 对象。JSON 对象的关键字之一是保留关键字。有没有解决的办法:

from dataclasses import dataclass
import jsons

out = {"yield": 0.21}

@dataclass
class PriceObj:
    asOfDate: str
    price: float
    yield: float

jsons.load(out, PriceObj)
Run Code Online (Sandbox Code Playgroud)

这显然会失败,因为yield是保留的。查看数据类field定义,似乎没有任何可以提供帮助的内容。

Go,允许定义JSON字段的名称,不知道里面有没有这样的功能dataclass

python json python-3.x python-dataclasses

6
推荐指数
1
解决办法
856
查看次数

如何比较数据类?

我想比较两个全局数据类的相等性。我更改了其中一个数据类中的字段,但 python 仍然坚持告诉我,这些对象是相等的。我不知道数据类内部如何工作,但是当我打印时,asdict我得到一个空字典...我做错了什么以及如何通过检查其成员的相等性来比较数据类?

我正在使用Python 3.9.4

from dataclasses import dataclass, asdict

@dataclass
class TestClass:
    field1 = None
    field2 = False

test1 = TestClass()
test2 = TestClass()

def main():
    global test1
    global test2

    test2.field2 = True

    print('Test1:        ', id(test1), asdict(test1), test1.field1, test1.field2)
    print('Test2:        ', id(test2), asdict(test2), test2.field1, test2.field2)
    print('Are equal?    ', test1 == test2)
    print('Are not equal?', test1 != test2)

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

输出:

Test1:         2017289121504 {} None False
Test2:         2017289119296 {} None True
Are equal?     True
Are …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

6
推荐指数
1
解决办法
6975
查看次数

如何让 Python 数据类 InitVar 字段与 Typing.get_type_hints 一起使用,同时还使用注释?

当处理 Python 数据类时,我遇到了这个很容易重现的奇怪错误。

from __future__ import annotations

import dataclasses as dc
import typing

@dc.dataclass
class Test:
    foo: dc.InitVar[int]

print(typing.get_type_hints(Test))
Run Code Online (Sandbox Code Playgroud)

运行它会得到以下结果:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    print(typing.get_type_hints(Test))
  File "C:\Program Files\Python310\lib\typing.py", line 1804, in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
  File "C:\Program Files\Python310\lib\typing.py", line 324, in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
  File "C:\Program Files\Python310\lib\typing.py", line 687, in _evaluate
    type_ =_type_check(
  File "C:\Program Files\Python310\lib\typing.py", line 173, in _type_check
    raise TypeError(f"{msg} Got {arg!r:.100}.")
TypeError: Forward references must evaluate …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses python-typing python-3.10

6
推荐指数
1
解决办法
2133
查看次数

我可以创建数据类实例的枚举吗?

我有一组固定的三个传感器,我想将其建模为枚举。每个传感器都通过一些不同的属性进行参数化。因此,我想将传感器本身建模为数据类。

我天真的尝试看起来像这样:

@dataclass
class SensorLocation:
    address: int
    pins: int
    other_details: ...

class Sensors(SensorLocation, Enum):
    TOP_SENSOR = SensorLocation(address=0x10, pins=0xf,  other_details=...)
    BOTTOM_SENSOR = SensorLocation(address=0x10, pins=0xf0,  other_details=...)
    SIDE_SENSOR = SensorLocation(address=0x15, pins=0xf,  other_details=...)
Run Code Online (Sandbox Code Playgroud)

我的期望是,这本质上应该创建一个枚举,其中该枚举的实例的行为类似于SensorLocation. 这使得类型更加清晰,并将方法放在我期望的位置。

但是,在创建枚举时失败,并出现错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/python/3.7.10/lib/python3.7/enum.py", line 232, in __new__
    enum_member.__init__(*args)
  File "<string>", line 3, in __init__
  File "/path/to/python/3.7.10/lib/python3.7/types.py", line 175, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)

我能做的是删除SensorLocation枚举声明中的子类化,但这意味着当使用 MyPy 或类似工具时,我失去了键入提示正确值的能力。它还使访问实际值变得更加复杂,但该枚举的主要目的是提供对这些值的访问。

有没有办法解决我缺少的这个错误,或者我现在看不到的其他解决方案?

python enums python-dataclasses

6
推荐指数
1
解决办法
2812
查看次数

从数据类中的自定义构造函数调用生成的 __init__ 作为默认值

是否可以从 中受益dataclasses.field,特别是对于默认值,但使用自定义构造函数?我知道@dataclass注释在生成的中设置默认值__init__,如果我替换它,就不会再这样做了。那么,是否可以替换生成的__init__,并仍然在内部调用它?

@dataclass
class A:
    l: list[int] = field(default_factory=list)
    i: int = field(default=0)
        
    def __init__(self, a: Optional[int]): # completely different args than instance attributes
        self.call_dataclass_generated_init() # call generated init to set defaults
        if a is not None: # custom settings of attributes
            i = 2*a
Run Code Online (Sandbox Code Playgroud)

解决方法是定义__new__而不是覆盖__init__,但我更愿意避免这种情况。

  • 这个问题非常接近,但答案仅解决作为代码示例给出的特定用例。另外,我不想使用,__post_init__因为我需要使用__setattr__这是静态类型检查的问题,并且它无助于调整__init__无论如何都会采用的参数。

  • 我也不想使用类方法,我真的希望调用者使用自定义构造函数。

  • 这一个也很接近,但它只是解释为什么新的构造函数替换生成的构造函数,而不是关于如何仍然调用后者(还有一个回复建议使用 Pydantic,但我不想子类化BaseModel,因为这会弄乱我的继承权)。

因此,简而言之,我希望受益于dataclass …

python python-dataclasses

6
推荐指数
1
解决办法
1579
查看次数

初始化Python数据类对象而不传递实例变量或默认值

我想初始化 python 数据类对象,即使没有实例变量传递给它并且我们没有向参数添加默认值

@dataclass
class TestClass:
   
   paramA: str
   paramB: float
   paramC: str

obj1 = TestClass(paramA="something", paramB=12.3)

Run Code Online (Sandbox Code Playgroud)

这里它不允许我创建对象并且它会抛出

TypeError: __init__() missing 1 required positional argument: 'paramC'
Run Code Online (Sandbox Code Playgroud)

我可以使用默认值来解决此错误。

paramC: str = None
# OR
paramC: str = ""
Run Code Online (Sandbox Code Playgroud)

但我不想使用 paramC 的默认值,因为我想要一个场景,如果我们传递 paramC 那么只有它应该存在于对象中,否则它不应该存在。因此,如果我们在这里使用默认值,paramC 将始终存在于对象中,其值为None或空字符串。

如果在初始化期间未传递参数,我想跳过参数的初始化。

python python-3.x python-dataclasses

6
推荐指数
1
解决办法
6668
查看次数

数据类字段可以为 repr 格式化其值吗?

我有一个 Node 类,以十六进制和 HSV 形式保存 RGB 数据。我将使用它以各种方式对颜色进行排序,并且希望 HSV 元组保持浮点形式进行比较,而不是每次使用时都从字符串进行转换。有没有一种方法可以指定数据类字段应该以类似于默认值的特定方式格式化值default_factory,即 a repr_factory

def RGB2HSV(r, g, b):
    '''Returns HSV values in the range H = [0, 360], S = [0, 100], V = [0, 100]'''
    r, g, b = r / 255, g / 255, b / 255
    maxRGB = max(r, g, b)
    minRGB = min(r, g, b)
    delta = maxRGB - minRGB

    V = maxRGB
    if V == 0:
        return 0, 0, V
    
    S = delta / V …
Run Code Online (Sandbox Code Playgroud)

python repr python-dataclasses

6
推荐指数
1
解决办法
1947
查看次数

是否可以使用 dataclass 而不是 typeddict 来定义 dict 类型并使 mypy 满意?

我有一个数据类,比方说:

from dataclasses import dataclass

@dataclass
class Foo:
    bar: int
    baz: int
Run Code Online (Sandbox Code Playgroud)

我有一个从接收 json 并将其作为字典加载的 API 调用的函数:

def handler(foo) -> Foo:
    return Foo(**foo)
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以输入 foo 而无需实际创建TypedDict数据类的镜像?

例如:

from typing_extensions import TypedDict


class SerializedFoo(TypedDict):
    bar: int
    baz: int
Run Code Online (Sandbox Code Playgroud)

我觉得必须定义两者很奇怪。

python mypy python-dataclasses python-typing typeddict

6
推荐指数
1
解决办法
2415
查看次数