我想创建一个类层次结构,其中类的所有对象Base都有一个字段field1,但不同的子类有不同的默认值field1。这些类是数据持有者,因此dataclasses看起来是一个完美的库。
考虑以下 python 3.7+ 代码。
from dataclasses import dataclass, field
from typing import Any, Iterable
@dataclass
class Base:
field1: Iterable[Any]
@dataclass
class Sub(Base):
field2: Any
field1: Iterable[Any] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
代码失败,给了我TypeError: non-default argument 'field2' follows default argument. 这有点令人惊讶,因为遵循超类的field2非默认参数,而该类的默认参数实际上位于.field1field1Subfield2
根据有关数据类继承的文档中的示例,子类中的字段会覆盖超类中的字段,但保留字段顺序。所以这个错误是有道理的。
这里有任何合适的解决方法,还是我必须手动实现所有内容?
我有一个这样设置的数据类:
from dataclasses import dataclass, field
from typing import List
@dataclass
class stats:
target_list: List[None] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
当我尝试像这样比较列表的内容时:
if stats.target_list == None:
pass
Run Code Online (Sandbox Code Playgroud)
我得到 AttributeError: type object 'stats' has no attribute 'target_list'
我该如何解决这个问题?谢谢
我正在优化我的代码以提高性能,当我用来cProfile检查我的代码时,大量的运行时间是由于类型注释造成的!删除类型注释确实可以提高性能。cProfiler您可以在下面看到带注释和不带注释的输出。
带注释的明显使用了__call__、__new__、inner、__getitem__、__hash__等方法typing.py,而且比不带注释的慢了一倍!
我的测试代码很简单:
from reil.datatypes import reildata
x = reildata.Categorical(name='cat', categories=('A', 'B', 'C', 'D', 'E'))
for _ in range(10000):
[x(v) for v in ('A', 'B', 'C', 'D', 'E')]Run Code Online (Sandbox Code Playgroud)
这是主代码的相关部分(datatypes.reildata.py):
from __future__ import annotations
import dataclasses
import itertools
from dataclasses import field
from typing import Any, Callable, Dict, Generic, Iterable, Iterator, List, Optional, Sequence, Tuple, TypeVar, Union, cast
from typing_extensions import …Run Code Online (Sandbox Code Playgroud)假设我有一个带有 set 方法的数据类。如何扩展 repr 方法,以便在调用 set 方法时它也会更新:
from dataclasses import dataclass
@dataclass
class State:
A: int = 1
B: int = 2
def set(self, var, val):
setattr(self, var, val)
Run Code Online (Sandbox Code Playgroud)
前任:
In [2]: x = State()
In [3]: x
Out[3]: State(A=1, B=2)
In [4]: x.set("C", 3)
In [5]: x
Out[5]: State(A=1, B=2)
In [6]: x.C
Out[6]: 3
Run Code Online (Sandbox Code Playgroud)
我想要的结果
In [7]: x
Out[7]: State(A=1, B=2, C=3)
Run Code Online (Sandbox Code Playgroud) h.json考虑这个名为“我想将其转换为 python 数据类”的 json 文件。
{
"acc1":{
"email":"acc1@example.com",
"password":"acc1",
"name":"ACC1",
"salary":1
},
"acc2":{
"email":"acc2@example.com",
"password":"acc2",
"name":"ACC2",
"salary":2
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用替代构造函数来获取每个帐户,例如:
import json
from dataclasses import dataclass
@dataclass
class Account(object):
email:str
password:str
name:str
salary:int
@classmethod
def from_json(cls, json_key):
file = json.load(open("h.json"))
return cls(**file[json_key])
Run Code Online (Sandbox Code Playgroud)
但这仅限于数据类中定义的参数(电子邮件、姓名等)。
如果我要修改 json 以包含其他内容(例如年龄)怎么办?该脚本最终将返回一个TypeError,特别是TypeError: __init__() got an unexpected keyword argument 'age'.
有没有办法根据dict(json对象)的键动态调整类属性,这样我就不必每次向json添加新键时都添加属性?
似乎已经对此进行了相当多的讨论。我发现这篇文章特别有帮助,它似乎提供了最好的解决方案之一。
但推荐的解决方案存在问题。
嗯,一开始看起来效果很好。考虑一个没有属性的简单测试用例:
@dataclass
class Foo:
x: int
Run Code Online (Sandbox Code Playgroud)
>>> # Instantiate the class
>>> f = Foo(2)
>>> # Nice, it works!
>>> f.x
2
Run Code Online (Sandbox Code Playgroud)
x现在尝试使用推荐的解决方案作为属性来实现:
@dataclass
class Foo:
x: int
_x: int = field(init=False, repr=False)
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
Run Code Online (Sandbox Code Playgroud)
>>> # Instantiate while explicitly passing `x`
>>> f = Foo(2)
>>> # Still appears to work
>>> f.x
2
Run Code Online (Sandbox Code Playgroud)
可是等等...
>>> # Instantiate without any arguments
>>> f …Run Code Online (Sandbox Code Playgroud) 我想解析 json 并将其保存在数据类中以模拟 DTO。目前,我必须手动将所有 json 字段传递给数据类。我想知道有没有一种方法可以通过添加 json 解析的字典来做到这一点。“dejlog”到数据类,所有字段都会自动填充。
from dataclasses import dataclass, asdict
@dataclass
class Dejlog(Dataclass):
PK: str
SK: str
eventtype: str
result: str
type: str
status: str
def lambda_handler(event, context):
try:
dejlog = json.loads(event['body'])
x = Dejlog(dejlog['PK'])
print(x)
print(x.PK)
Run Code Online (Sandbox Code Playgroud) 概括
我有dataclass10多个字段。print()使用它们将有趣的上下文埋藏在默认值的墙中 - 让我们通过不再不必要地重复这些来使它们变得更友好。
Python 中的数据类
Python 的@dataclasses.dataclass()( PEP 557 ) 提供自动可打印表示 ( __repr__())。
假设这个例子,基于 python.org 的:
from dataclasses import dataclass
@dataclass
class InventoryItem:
name: str
unit_price: float = 1.00
quantity_on_hand: int = 0
Run Code Online (Sandbox Code Playgroud)
装饰器@dataclass(repr=True)(默认)将得到print()一个很好的输出:
InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
Run Code Online (Sandbox Code Playgroud)
我想要的:跳过打印默认值
repr它会打印所有字段,包括您不想显示的隐含默认值。
print(InventoryItem("Apple"))
# Outputs: InventoryItem(name='Apple', unit_price='1.00', quantity_on_hand=0)
# I want: InventoryItem(name='Apple')
Run Code Online (Sandbox Code Playgroud)
print(InventoryItem("Apple", unit_price="1.05"))
# Outputs: InventoryItem(name='Apple', unit_price='1.05', quantity_on_hand=0)
# I want: InventoryItem(name='Apple', unit_price='1.05') …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个函数来记录数据类,我想获取数据类中所有字段的名称并将值打印到每个字段(类似于编写一个函数来打印字典)
IE
@dataclasses.dataclass
class Test:
a: str = "a value"
b: str = "b value"
test = Test()
def print_data_class(dataclass_instance):
fields = # get dataclass fileds
for field in fields:
print(f{field}: {dataclass.field})
print_data_class(test)
-->
"a" : "a value"
"b" : "b value"
Run Code Online (Sandbox Code Playgroud)
但是我一直无法找到如何获取数据类的字段,有谁知道如何做到这一点?
谢谢
我想初始化 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 ×9
json ×2
python-3.x ×2
cprofile ×1
oop ×1
properties ×1
python-3.9 ×1
python-class ×1
repr ×1
type-hinting ×1