标签: 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
查看次数

禁止从类外部使用默认构造函数

考虑以下数据类。我想阻止使用直接方法创建对象__init__

from __future__ import annotations
from dataclasses import dataclass, field

@dataclass
class C:
    a: int

    @classmethod
    def create_from_f1(cls, a: int) -> C:
        # do something
        return cls(a)
    @classmethod
    def create_from_f2(cls, a: int, b: int) -> C:
        # do something
        return cls(a+b)

    # more constructors follow


c0 = C.create_from_f1(1) # ok

c1 = C()  # should raise an exception
c2 = C(1) # should raise an exception
Run Code Online (Sandbox Code Playgroud)

例如,我想强制使用我定义的附加构造函数,如果直接将对象创建为c = C(..).

到目前为止我所尝试的如下。

@dataclass
class C:
    a : int …
Run Code Online (Sandbox Code Playgroud)

python class python-3.7 python-dataclasses

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

数据类子类不继承 __repr__

我正在使用dataclasses从 Python 3.7 向后移植的Python模块。我偶然发现了这种行为,其中数据类子类不继承__repr__

from dataclasses import dataclass

@dataclass
class Person:
    name: str

    def __repr__(self):
        return f'{self.__class__.__qualname__}({self.name})'

    def print_something(self):
        return self.name

@dataclass
class Employee(Person):
    title: str
Run Code Online (Sandbox Code Playgroud)

这是输出

In [21]: e = Employee(name='Dmitry', title='Systems Engineer')

In [22]: p = Person(name='Dmitry')

In [23]: repr(e)
Out[23]: "Employee(name='Dmitry', title='Systems Engineer')"

In [24]: p = Person(name='Dmitry')

In [25]: repr(p)
Out[25]: 'Person(Dmitry)'

In [26]: p.print_something()
Out[26]: 'Dmitry'

In [27]: e = Employee(name='Dmitry', title='Systems Engineer')

In [28]: repr(e)
Out[28]: "Employee(name='Dmitry', title='Systems Engineer')"

In …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

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

如何使非冻结数据类冻结,反之亦然?

我想知道一种使数据类bar冻结的简单方法。

@dataclass
class Bar:
    foo: int
bar = Bar(foo=1)
Run Code Online (Sandbox Code Playgroud)

换句话说,我想要一个如下所示的函数some_fn_to_freeze

frozen_bar = some_fn_to_freeze(bar)
frozen_bar.foo = 2 # Error
Run Code Online (Sandbox Code Playgroud)

并且,反函数some_fn_to_unfreeze

bar = som_fn_to_unfrozen(frozen_bar)
bar.foo = 3 # not Error
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

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

Python数据类:可以为字段设置默认值吗?

我想创建一个数据类基类,其中子类中的所有字段自动为可选且默认为“无”(如果未提供默认值)。

下面的代码......似乎几乎达到了我想要的效果,但又不完全是。它的错误方式就像我从未编写过一样__init_subclass__(即抱怨未填充的参数)...也许是因为我的代码在数据类魔法发生后运行?

@dataclass(order=True, frozen=True)
class BaseDictKey:
    def __init_subclass__(cls, *args, **kwargs):
        super().__init_subclass__(*args, **kwargs)
        # noinspection PyUnresolvedReferences
        for field in cls.__dataclass_fields__.values():
            field.default = None if field.default is None else field.default
            field.type = typing.Union[field.type, NoneType]

@dataclass(order=True, frozen=True)
class ScoreDictKey(BaseDictKey):
    catalog: str  # magically becomes catalog: Optional[str] = None
    dataset: str = 'foo'  # magically becomes dataset: Optional[str] = 'foo'

Run Code Online (Sandbox Code Playgroud)

(如果您想知道为什么我想要这个,我有另一个使用这些 BaseDictKeys 的基类,它期望子类中的任何和所有字段都是可选的。我想如果我检测到某些内容不是可选的,我可以改为引发异常,但这看起来更丑陋。)

这在 Python 3.7+ 中可能吗?

python python-3.x python-dataclasses

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

如何将特定类型的 numpy 数组声明为数据类中的类型

我所拥有的:
我正在创建一个数据类,并说明其元素的类型:

class Task():  
     n_items: int  
     max_weight: int  
     max_size: int  
     items: numpy.array(Item)  # incorrect way of doing it
Run Code Online (Sandbox Code Playgroud)

我想做的事情是
我想声明,该items将是“Item”类的对象的 numpy 数组

python-3.x numpy-ndarray python-dataclasses

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

Python:数据类的循环依赖/前向变量声明?

所以,我在一个文件中有这两个数据类:

@dataclass
class A:
    children: List[B]

@dataclass
class B:
    parent: A
Run Code Online (Sandbox Code Playgroud)

,这可以通过使用该__future__.annotations功能来实现。

然后我有另外两个文件,每个文件都有一堆对于我的项目来说是静态的每种类型的对象。

文件objects_A

import objects_B

obj_a1 = A(
    children=[
        objects_B.obj_b1,
        objects_B.obj_b2
    ]
)
Run Code Online (Sandbox Code Playgroud)

文件objects_B

import objects_A

obj_b1 = B(
    parent=objects_A.obj_a1
)

obj_b2 = B(
    parent=objects_A.obj_a1
)
Run Code Online (Sandbox Code Playgroud)

显然,文件之间存在循环依赖问题,但即使它们位于同一个文件中,它也不起作用,因为一种类型的变量依赖于另一种类型的变量才能成功。
初始化B内部对象obj_a1也不起作用,因为self这里没有概念。

目前,我设置parentNone(针对类型提示),然后循环进行设置obj_a1

for obj_b in obj_a1.children:
    obj_b.parent = obj_a1
Run Code Online (Sandbox Code Playgroud)

大家有什么好主意吗?
不知道它是否有帮助,但是这些对象是静态的(它们在这些声明之后不会改变)并且它们具有某种父子关系(正如您肯定已经注意到的那样)。
如果可能的话,我希望将每种类型的变量放在不同的文件中。

python forward-declaration circular-reference python-3.x python-dataclasses

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

Python数据类生成哈希并排除不安全字段

我有这个数据类:

from dataclasses import dataclass, field
from typing import List

@dataclass
class Person:
    name: str
    dob: str
    friends: List['Person'] = field(default_factory=list, init=False)
Run Code Online (Sandbox Code Playgroud)

name并且dob是不可变的并且friends是可变的。我想生成每个人对象的哈希值。我可以以某种方式指定要包含和排除哪个字段来生成__hash__ 方法吗?在这种情况下,namedob应该包含在生成哈希中,但friends不应该包含。这是我的尝试,但没有成功

@dataclass
class Person:
    name: str = field(hash=True)
    dob: str = field(hash=True)
    friends: List['Person'] = field(default_factory=list, init=False, hash=False)
Run Code Online (Sandbox Code Playgroud)
>>> hash(Person("Mike", "01/01/1900"))
Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    hash(Person("Mike", "01/01/1900"))
TypeError: unhashable type: 'Person'
Run Code Online (Sandbox Code Playgroud)

我也找不到设置namedob冻结的方法。仅仅从声音来看,我不会将其设置unsafe_hash为。 …

python python-dataclasses

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

如何注释数据类中字段的类型与其 __init__ 的类型不同?

我创建了一个数据类Foo,它接受任何可以转换为的类型int

import dataclasses


@dataclasses.dataclass
class Foo:
    a: int

    def __post_init__(self):
        # Here `self.a` is converted to int, so this class accepts any type that can be converted to int
        self.a = int(self.a)


# mypy error: Argument 1 to "Foo" has incompatible type "str"; expected "int",
foo = Foo("1")
print(foo)
print(foo.a + 2)
Run Code Online (Sandbox Code Playgroud)

输出:

Foo(a=1)
3
Run Code Online (Sandbox Code Playgroud)

但是,mypy 报告以下错误:

error: Argument 1 to "Foo" has incompatible type "str"; expected "int"
Run Code Online (Sandbox Code Playgroud)

Foo.a如果我修复to的类型Union[str, int],mypy 会报告另一个错误:

error: Unsupported …
Run Code Online (Sandbox Code Playgroud)

python mypy python-dataclasses

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

在具有泛型类型的类中定义的数据类的类型提示

我知道标题很混乱,所以让我以二叉搜索树为例:

使用普通的类定义

# This code passed mypy test
from typing import Generic, TypeVar

T = TypeVar('T')
class BST(Generic[T]):
    class Node:        
        def __init__(
            self,
            val: T,
            left: 'BST.Node',
            right: 'BST.Node'
        ) -> None:
            self.val = val
            self.left = left
            self.right = right
Run Code Online (Sandbox Code Playgroud)

上面的代码通过了mypy测试。

使用dataclass

但是,当我尝试使用dataclass来简化 的定义时Node,代码在 mypy 测试中失败了。

# This code failed to pass mypy test
from dataclasses import dataclass
from typing import Generic, TypeVar

T = TypeVar('T')
class BST(Generic[T]):
    @dataclass
    class Node:
        val: …
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses python-typing

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