如何将值从基础数据类升级到继承自它的数据类?
示例(Python 3.7.2)
from dataclasses import dataclass
@dataclass
class Person:
name: str
smell: str = "good"
@dataclass
class Friend(Person):
# ... more fields
def say_hi(self):
print(f'Hi {self.name}')
friend = Friend(name='Alex')
f1.say_hi()
Run Code Online (Sandbox Code Playgroud)
打印“嗨亚历克斯”
random_stranger = Person(name = 'Bob', smell='OK')
Run Code Online (Sandbox Code Playgroud)
返回 random_stranger "Person(name='Bob',sole='OK')"
如何将 random_stranger 变成朋友?
Friend(random_stranger)
Run Code Online (Sandbox Code Playgroud)
返回“朋友(姓名=人(姓名='鲍勃',气味='OK'),气味='好')”
结果我想得到“朋友(名字=“鲍勃”,气味=“OK”)”。
Friend(random_stranger.name, random_stranger.smell)
Run Code Online (Sandbox Code Playgroud)
有效,但如何避免必须复制所有字段?
或者我是否可能无法在从数据类继承的类上使用 @dataclass 装饰器?
目前我像这样使用了 DTO(数据传输对象)。
class Test1:
def __init__(self,
user_id: int = None,
body: str = None):
self.user_id = user_id
self.body = body
Run Code Online (Sandbox Code Playgroud)
示例代码很小,但是当对象规模越来越大时,我必须定义每个变量。
在深入研究的同时,发现python 3.7支持 dataclass
下面的代码是 DTO 使用的数据类。
from dataclasses import dataclass
@dataclass
class Test2:
user_id: int
body: str
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如何允许传递更多未定义为的参数class Test2?
如果我使用Test1,这很容易。只需添加**kwargs(asterisk)到__init__
class Test1:
def __init__(self,
user_id: int = None,
body: str = None,
**kwargs):
self.user_id = user_id
self.body = body
Run Code Online (Sandbox Code Playgroud)
但是使用数据类,找不到任何方法来实现它。
这里有什么解决办法吗?
谢谢。
编辑
class Test1:
def __init__(self,
user_id: str = None,
body: …Run Code Online (Sandbox Code Playgroud) 我正在尝试构建一个@dataclass定义架构但实际上并未使用给定成员实例化的模型。(基本上,我@dataclass为了其他目的劫持了方便的语法)。这几乎就是我想要的:
@dataclass(frozen=True, init=False)
class Tricky:
thing1: int
thing2: str
def __init__(self, thing3):
self.thing3 = thing3
Run Code Online (Sandbox Code Playgroud)
但是我FrozenInstanceError在__init__方法中得到了一个:
dataclasses.FrozenInstanceError: cannot assign to field 'thing3'
Run Code Online (Sandbox Code Playgroud)
我需要frozen=True(为了哈希)。有什么方法可以在__init__冻结上设置自定义属性@dataclass吗?
我有一个字段template类型为 Enum的数据类。使用该asdict函数时,它将我的数据类转换为字典。是否可以使用valueof 属性FoobarEnum来返回字符串值而不是 Enum 对象?
我最初的想法是使用函数的dict_factory=dict参数asdict并提供我自己的工厂,但我不知道如何做到这一点。
from dataclasses import dataclass, asdict
from enum import Enum
@dataclass
class Foobar:
name: str
template: "FoobarEnum"
class FoobarEnum(Enum):
FIRST = "foobar"
SECOND = "baz"
foobar = Foobar(name="John", template=FoobarEnum.FIRST)
print(asdict(foobar))
Run Code Online (Sandbox Code Playgroud)
电流输出:
{'name': 'John', 'template': <FoobarEnum.FIRST: 'foobar'>}
Run Code Online (Sandbox Code Playgroud)
目标:
{'name': 'John', 'template': 'foobar'}
Run Code Online (Sandbox Code Playgroud) 我正在尝试做相当于:
class A:
def __init__(self):
self.b = self.get_b()
def get_b(self):
return 1
Run Code Online (Sandbox Code Playgroud)
使用@dataclass。我想在这里使用 a ,@dataclass因为还有其他(省略的)字段是从提供的构造函数参数初始化的。b是从实例方法的结果初始化的字段之一。执行这个:
@dataclass
class A:
b = self.get_b()
def get_b(self):
return 1
Run Code Online (Sandbox Code Playgroud)
表明self未在 的b范围内定义。这里可以参考一下吗self?
我想创建一个 Pydantic 模型,其中有一个列表字段,未初始化的默认值为空列表。有没有一种惯用的方法来做到这一点?
对于 Python 的内置数据类对象,您可以使用field(default_factory=list),但是在我自己的实验中,这似乎可以防止我的 Pydantic 模型被腌制。一个天真的实现可能是这样的:
from pydantic import BaseModel
class Foo(BaseModel):
defaulted_list_field: Sequence[str] = [] # Bad!
Run Code Online (Sandbox Code Playgroud)
但是我们都知道不要使用像空列表文字这样的可变值作为默认值。
那么给 Pydantic 列表字段一个默认值的正确方法是什么?
我开始大量使用 python dataclasses 模块并发现它非常有用。我特别喜欢可以在每个字段上设置的标志,允许切换比较、初始化等。
然而,我经常发现,有一个领域我希望从班级的沉迷行为中省略。在某些情况下,使用 dict_factory 参数可能会实现这一点,但有时,某个字段会导致 asdict 函数在通过使用 dict_factory 省略该字段之前引发异常。
其他人可以建议一种干净的方法来做到这一点吗?添加到数据类模块中不是一个有用的附加标志吗?
我想使用该方法填充数据类的属性default_factory。但是,由于工厂方法仅在该特定类的上下文中有意义,因此我想将其保留在类内部(例如作为静态或类方法)。例如:
from dataclasses import dataclass, field
from typing import List
@dataclass
class Deck:
cards: List[str] = field(default_factory=self.create_cards)
@staticmethod
def create_cards():
return ['King', 'Queen']
Run Code Online (Sandbox Code Playgroud)
但是,我在第 6 行收到此错误(如预期):
NameError:名称“self”未定义
我怎样才能克服这个问题?我不想将该create_cards()方法移出类。
是否可以指定在非冻结数据类中冻结单个字段?像这样的东西:
@dataclass
class Data:
fixed: int = field(frozen=True)
mutable: int = field(frozen=False)
d = Data(2, 3)
d.mutable = 5 # fine
d.fixed = 7 # raises exception
Run Code Online (Sandbox Code Playgroud)
我意识到这可以通过访问私有数据字段的属性和设置器手动完成,但是这样我们就失去了数据类的一些优点:首先,私有数据字段需要不同的名称,这意味着自动生成的构造函数令人烦恼地具有不同的名称参数名称比字段更重要。
我经常看到这样的代码:
@dataclass
class ClassName:
list_name: list[int] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么我需要输入field(default_factory=list). 还不够吗list_name: list[int]?
您能解释一下何时、为什么以及如何在数据类中使用 field() 吗?