我有一个数据类,比方说:
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)
我觉得必须定义两者很奇怪。
TypeScript has a Pick type which can take an existing type and create a new one by picking individual attributes. I would like to have a similar functionality in Python, so for example:
from dataclasses import dataclass
from pick import Pick
@dataclasses.dataclass
class Foo:
x: int
y: float
z: str
Bar = Pick(Foo, ('x', 'y'))
foo = Foo(1, 2.0, '3')
bar = Bar(1, 2.0)
Run Code Online (Sandbox Code Playgroud)
I want this to avoid the problem of partial object population without having to explicitly define …
随着python数据类装饰器的最新介绍,编写模型类非常容易。
但是我不确定如何在自引用结构/模型类的上下文中使用-例如LinkedList的内部ListNode / Node模型类。
>>> from dataclasses import dataclass
>>> from typing import Type
>>>
>>> @dataclass
... class Node:
... data: int
... link: Node
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in Node
NameError: name 'Node' is not defined
>>>
>>>
>>> @dataclass
... class Node:
... data: int
... link: Type[Node] # have tried Type hinting
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module> …Run Code Online (Sandbox Code Playgroud) 在Python 3.7中,我可以使用默认值创建一个数据类InitVar:
from dataclasses import dataclass, InitVar, field
@dataclass
class Foo:
seed: InitVar[str] = field(default='tomato')
stored: str = field(init=False)
def __post_init__(self, seed: str):
self.stored = f'planted {seed}'
print(Foo())
Run Code Online (Sandbox Code Playgroud)
现在,我尝试创建一个具有可变默认值的类似数据类,而我需要使用它:default_factory
from dataclasses import dataclass, InitVar, field
from typing import List
@dataclass
class Bar:
seeds: InitVar[List[str]] = field(default_factory=list)
stored: List[str] = field(init=False)
def __post_init__(self, seeds: List[str]):
self.stored = [f'planted {seed}' for seed in seeds]
print(Bar())
Run Code Online (Sandbox Code Playgroud)
但是,这是无效的。Python加注TypeError: field seeds cannot have a default factory …
在我试图创建一个类dots与领域n,并xy如下图所示:
from dataclasses import dataclass
@dataclass
class dots:
n: int = 200
xy: List[int] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
我不断收到错误:
NameError: name 'field' is not defined
Run Code Online (Sandbox Code Playgroud)
关于如何解决它的任何想法?
我的操作系统是 Ubuntu 18.04.3 LTS,内核版本是 4.15.0-58-generic。我正在使用 Python 3.6.4
我有一个这样的数据类:
@dataclass
class Bla:
arg1: Optional[int] = None
arg2: Optional[str] = None
arg3: Optional[Dict[str, str]] = None
Run Code Online (Sandbox Code Playgroud)
我想要这种行为:
>>> bla = Bla(arg1=None, arg2=None, arg3=None)
>>> asdict(bla)
{'arg1': None, 'arg2': None, 'arg3': None}
>>> bla = Bla()
{}
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,我可以使用 a dict,但我会失去类型提示的可能性(并使用 mypy)
所以我试过这个:
class none:
...
@dataclass
class Bla:
arg1: Union[none, int] = none()
arg2: Union[none, str] = none()
arg3: Union[none, Dict[str, str]] = none()
def __post_init__(self) -> None:
for k, v in self.__dict__.copy().items():
if isinstance(v, none):
delattr(self, k)
Run Code Online (Sandbox Code Playgroud)
但结果是: …
在这段代码中:
import dataclasses
@dataclasses.dataclass
class MyClass:
value: str
obj = MyClass(value=1)
Run Code Online (Sandbox Code Playgroud)
数据类MyClass使用不遵守value类型的值进行实例化。
是否有一种简单的方法(使用装饰器、dataclass装饰器或库中的参数)来强制字段的类型,以便我的示例中的最后一行引发 aValueError或类似的东西?以这种方式强制执行类型有什么主要缺点吗?
我在尝试将数据类与属性一起使用时遇到了一个奇怪的问题。
我把它降到最低限度来重现它:
import dataclasses
@dataclasses.dataclass
class FileObject:
_uploaded_by: str = dataclasses.field(default=None, init=False)
uploaded_by: str = None
def save(self):
print(self.uploaded_by)
@property
def uploaded_by(self):
return self._uploaded_by
@uploaded_by.setter
def uploaded_by(self, uploaded_by):
print('Setter Called with Value ', uploaded_by)
self._uploaded_by = uploaded_by
p = FileObject()
p.save()
Run Code Online (Sandbox Code Playgroud)
这输出:
Setter Called with Value <property object at 0x7faeb00150b0>
<property object at 0x7faeb00150b0>
Run Code Online (Sandbox Code Playgroud)
我希望得到 None 而不是
我在这里做错了什么还是偶然发现了一个错误?
在阅读@juanpa.arrivillaga 的回答后,我认为使 upload_by 和 InitVar 可能会解决问题,但它仍然返回一个属性对象。我想是因为这个,他说:
datalcas 机制将对类主体中的类型注释变量的任何赋值解释为 created 的默认值
__init__。
我能找到的适用于默认值的唯一选项是从数据类定义中删除 uploadby 并编写一个实际的__init__. 这有一个不幸的副作用,即要求您__init__手动为数据类编写一个,这否定了使用数据类的一些价值。这是我所做的:
import dataclasses …Run Code Online (Sandbox Code Playgroud) 即使一个类是从 继承的ABC,看起来它仍然可以被实例化,除非它包含抽象方法。
有了下面的代码,防止Identifier创建对象的最佳方法是什么:Identifier(['get', 'Name'])?
from abc import ABC
from typing import List
from dataclasses import dataclass
@dataclass
class Identifier(ABC):
sub_tokens: List[str]
@staticmethod
def from_sub_tokens(sub_tokens):
return SimpleIdentifier(sub_tokens) if len(sub_tokens) == 1 else CompoundIdentifier(sub_tokens)
@dataclass
class SimpleIdentifier(Identifier):
pass
@dataclass
class CompoundIdentifier(Identifier):
pass
Run Code Online (Sandbox Code Playgroud)
如果这个问题已经得到回答,我提前道歉。这看起来很基本,但是,由于某种原因我找不到答案。
干杯,赫利卜。
我有一堆@dataclasses 和一堆对应的TypedDicts,我想促进它们之间的平滑和类型检查转换。
例如,考虑
from dataclasses import dataclass
from typing_extensions import TypedDict
@dataclass
class Foo:
bar: int
baz: int
@property
def qux(self) -> int:
return bar + baz
class SerializedFoo(TypedDict):
bar: int
baz: int
qux: int
Run Code Online (Sandbox Code Playgroud)
要创建序列化函数,我可以编写类似
def serialize(foo: Foo) -> SerializedFoo:
return SerializedFoo(
bar=foo.bar,
baz=foo.baz,
qux=foo.qux,
)
Run Code Online (Sandbox Code Playgroud)
但是对于很多类型这样做变得乏味,而且每次更新类型时,我还必须更新序列化功能。
我也可以做类似的事情
def serialize(foo: Foo) -> SerializedFoo:
return SerializedFoo(**dataclasses.asdict(foo))
Run Code Online (Sandbox Code Playgroud)
但这不会进行类型检查;mypy抱怨它Expected keyword arguments, {...}, or dict(...) in TypedDict constructor。
从理论上讲,足够聪明的类型检查器应该有可能知道数据类具有初始化类型字典所需的属性,但是当然,使用asdict使得这在实践中是不可能的。
有没有更好的方法将 a 转换 …
python ×8
python-3.x ×6
mypy ×3
python-3.7 ×2
typeddict ×2
abc ×1
oop ×1
properties ×1
typescript ×1
typing ×1