我需要一个类函数,它可以根据现有实例属性创建一个新实例。
在我看来,这是一个工厂函数(因此认为它可能是一个类方法),但它需要实例化该类。
我应该/可以使用装饰器吗
@classmethod
?
from dataclasses import dataclass
@dataclass
class Coin:
obverse: str
reverse: str
def flip(self):
return Coin(self.reverse, self.obverse)
cent = Coin('cent_ob', 'cent_rev')
flipped_cent = cent.flip()
cent
Out[20]: Coin(obverse='cent_ob', reverse='cent_rev')
flipped_cent
Out[21]: Coin(obverse='cent_rev', reverse='cent_ob')
这有效。
但是如果我使用装饰器
@classmethod
,它就不再是了。
from dataclasses import dataclass
@dataclass
class Coin:
obverse: str
reverse: str
@classmethod
def flip(cls, self):
return cls(self.reverse, self.obverse)
cent = Coin('cent_ob', 'cent_rev')
flipped_cent = cent.flip()
TypeError: Coin.flip() missing 1 required positional argument: 'self'
请问我在这里处理什么情况? 还有其他装饰器更适合这种情况吗?
我相信我的主要目标更多的是让装饰器明确指示“嘿,你这里有一个工厂函数”。
谢谢您的帮助!
无需将其设为
classmethod
,因为一个Coin
的状态不一定是您创建的所有硬币的状态。改为这样做:
from dataclasses import dataclass
@dataclass
class Coin:
obverse: str
reverse: str
def flip(self):
return Coin(self.reverse, self.obverse)
cent = Coin('cent_ob', 'cent_rev')
flipped_cent = cent.flip()
现在,如果您设想在代码中只有此类的一个实例,那么只需更改该单例的状态即可。您甚至可以不再担心字符串,只需存储一个变量来指示硬币是否翻转到与其初始状态相反的方向:
@dataclass
class Coin:
flipped = 0
def flip(self):
self.flipped = 1 & (self.flipped + 1)
用这个测试:
coin = Coin()
print(coin.flipped)
coin.flip()
print(coin.flipped)
coin.flip()
print(coin.flipped)
coin.flip()
print(coin.flipped)
最后,附带说明一下:有时,尤其是在棋盘游戏中,“翻转硬币”意味着将它抛到空中并随机赋予它一个新的状态。也许您可能想将此方法称为
turn_over
或类似名称。由你决定。