admin管理员组文章数量:1395264
I have a Protocol
subclass that defines objects with attributes from an external library:
class P(Protocol):
val: int
For testing purposes, I want to turn this protocol class into something I can instantiate easily. However, when I try to turn it into a dataclass, an error pops up:
import dataclasses
from typing import Protocol
class P(Protocol):
val: int
PInst = dataclasses.dataclass(P)
PInst(val=4) # TypeError: Protocols cannot be instantiated
Is there an easy solution to use P
to create a class that satifies its protocol and is instantiable, without redeclaring its attributes?
I have a Protocol
subclass that defines objects with attributes from an external library:
class P(Protocol):
val: int
For testing purposes, I want to turn this protocol class into something I can instantiate easily. However, when I try to turn it into a dataclass, an error pops up:
import dataclasses
from typing import Protocol
class P(Protocol):
val: int
PInst = dataclasses.dataclass(P)
PInst(val=4) # TypeError: Protocols cannot be instantiated
Is there an easy solution to use P
to create a class that satifies its protocol and is instantiable, without redeclaring its attributes?
1 Answer
Reset to default 2You are asking for a non-protocol class derived from the attributes in your protocol class. They are stored in the annotations, which are accessible as typing.get_type_hints(P)
.
In my first try, I dynamically created that class with builtin type
, passing it the protocol's type hints to define an equivalent non-protocol class, and pass that to dataclass
. But it needed me to manually set dunder annotations before it could correctly create the init method.
But messing with internal attributes is a red flag telling me there should be an easier way. So I looked at the dataclasses public interface and found make_dataclass
. You can just pass the annotations directly to its fields parameter.
from dataclasses import make_dataclass
from typing import Protocol, get_type_hints
class P(Protocol):
val: int
DP = make_dataclass('DP', get_type_hints(P))
instance = DP(val=4)
print(instance)
output:
DP(val=4)
本文标签: pythonHow to make an easily instantiable derivative attributeonly protocol classStack Overflow
版权声明:本文标题:python - How to make an easily instantiable derivative attribute-only protocol class? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744713316a2621256.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
P
is supposed to match;@dataclasses.dataclass
implicitly adds attributes (such as an__init__
), and the type-checker sees these implicit attributes, so it's unclear from your definition whether items which are supposed to matchP
should also include matching implicit attributes or not. If they should include matching implicit attributes, then just ditchProtocol
and subclass fromP
; otherwise I'd go for a class-based@typing.dataclass_transform
and switch the base class ofP
based on compile-time constants. – dROOOze Commented Mar 13 at 9:16defineConstant
configuration. – dROOOze Commented Mar 13 at 10:27Nominal
in dROOOze's example as a real case that you might encounter that follows the ProtocolP
, i.e. it is assignable toP
and nothing you need to define in your code. – Daraan Commented Mar 13 at 13:43Nominal
in the playground example is a nominal type placeholder for something in your real code that is assignable to the structural typeP
. From your example, the point of using a protocol (structural type) is that arbitrary nominal types in your real code can match this structural type without subclassing from P. – dROOOze Commented Mar 13 at 17:45