3 回答
TA贡献1821条经验 获得超6个赞
您所要求的是由工厂方法模式实现的,并且可以使用@classmethod关键字直接在 python 类中实现。
只需在基类定义中包含一个数据类工厂方法,如下所示:
import dataclasses
@dataclasses.dataclass
class Person:
name: str
smell: str = "good"
@classmethod
def from_instance(cls, instance):
return cls(**dataclasses.asdict(instance))
任何从这个基类继承的新数据类现在都可以像这样创建彼此的实例[1]:
@dataclasses.dataclass
class Friend(Person):
def say_hi(self):
print(f'Hi {self.name}')
random_stranger = Person(name = 'Bob', smell='OK')
friend = Friend.from_instance(random_stranger)
print(friend.say_hi())
# "Hi Bob"
[1]如果您的子类引入了没有默认值的新字段,您尝试从子类实例创建父类实例,或者您的父类具有 init-only 参数,则它将不起作用。
TA贡献2016条经验 获得超9个赞
您可能不希望class自身成为可变属性,而是使用诸如枚举之类的东西来指示诸如此类的状态。根据要求,您可以考虑以下几种模式之一:
class RelationshipStatus(Enum):
STRANGER = 0
FRIEND = 1
PARTNER = 2
@dataclass
class Person(metaclass=ABCMeta):
full_name: str
smell: str = "good"
status: RelationshipStatus = RelationshipStatus.STRANGER
@dataclass
class GreetablePerson(Person):
nickname: str = ""
@property
def greet_name(self):
if self.status == RelationshipStatus.STRANGER:
return self.full_name
else:
return self.nickname
def say_hi(self):
print(f"Hi {self.greet_name}")
if __name__ == '__main__':
random_stranger = GreetablePerson(full_name="Robert Thirstwilder",
nickname="Bobby")
random_stranger.status = RelationshipStatus.STRANGER
random_stranger.say_hi()
random_stranger.status = RelationshipStatus.FRIEND
random_stranger.say_hi()
您可能还想以 trait/mixin 风格实现这一点。不是创建一个GreetablePerson,而是创建一个类Greetable,也是抽象的,并使您的具体类继承这两者。
您还可以考虑使用出色的、反向移植的、更灵活的attrs软件包。这也将使您能够使用以下evolve()功能创建一个新对象:
friend = attr.evolve(random_stranger, status=RelationshipStatus.FRIEND)
TA贡献1780条经验 获得超3个赞
vars(stranger)为您提供数据类实例的所有属性的字典stranger。由于__init__()dataclasses的默认方法采用关键字参数,twin_stranger = Person(**vars(stranger))因此使用值的副本创建一个新实例。如果您提供额外的参数,这也适用于派生类stranger_got_friend = Friend(**vars(stranger), city='Rome'):
from dataclasses import dataclass
@dataclass
class Person:
name: str
smell: str
@dataclass
class Friend(Person):
city: str
def say_hi(self):
print(f'Hi {self.name}')
friend = Friend(name='Alex', smell='good', city='Berlin')
friend.say_hi() # Hi Alex
stranger = Person(name='Bob', smell='OK')
stranger_got_friend = Friend(**vars(stranger), city='Rome')
stranger_got_friend.say_hi() # Hi Bob
添加回答
举报