我可以实现一个调用实例属性的类方法吗?

问题描述 投票:0回答:1

我需要一个类函数,它可以根据现有实例属性创建一个新实例。

在我看来,这是一个工厂函数(因此认为它可能是一个类方法),但它需要实例化该类。

我应该/可以使用装饰器吗

@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'

请问我在这里处理什么情况? 还有其他装饰器更适合这种情况吗?

我相信我的主要目标更多的是让装饰器明确指示“嘿,你这里有一个工厂函数”。

谢谢您的帮助!

python class-method
1个回答
0
投票

无需将其设为

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
或类似名称。由你决定。

© www.soinside.com 2019 - 2024. All rights reserved.