Python for? のクラスメソッドとは)==を読みましたが、その投稿の例は複雑です。 Pythonのクラスメソッドの特定のユースケースの。
Python classmethodがジョブに適したツールになるような、小規模で具体的な使用例に名前を付けられますか?
初期化のヘルパーメソッド:
class MyStream(object):
@classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
@classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...
まあ___new__
_は非常に重要なクラスメソッドです。インスタンスは通常どこから来るのですか
so dict()
はもちろん_dict.__new__
_を呼び出しますが、時々辞書を作成する別の便利な方法があります。それはclassmethod dict.fromkeys()
です
例えば。
_>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
_
私は知りません、名前付きコンストラクターメソッドのようなものですか?
class UniqueIdentifier(object):
value = 0
def __init__(self, name):
self.name = name
@classmethod
def produce(cls):
instance = cls(cls.value)
cls.value += 1
return instance
class FunkyUniqueIdentifier(UniqueIdentifier):
@classmethod
def produce(cls):
instance = super(FunkyUniqueIdentifier, cls).produce()
instance.name = "Funky %s" % instance.name
return instance
使用法:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
私はほとんどの場合_@classmethod
コードをクラスに関連付けるため、コードを使用するためにクラスのインスタンスを必要としない場合に、グローバル関数の作成を回避するため。
たとえば、キーが何らかのパターンに準拠している場合にのみキーを有効と見なすデータ構造を持つ場合があります。これをクラスの内外で使用したい場合があります。ただし、さらに別のグローバル関数を作成する必要はありません。
def foo_key_is_valid(key):
# code for determining validity here
return valid
このコードを、それが関連付けられているクラスとグループ化することをお勧めします。
class Foo(object):
@classmethod
def is_valid(cls, key):
# code for determining validity here
return valid
def add_key(self, key, val):
if not Foo.is_valid(key):
raise ValueError()
..
# lets me reuse that method without an instance, and signals that
# the code is closely-associated with the Foo class
Foo.is_valid('my key')
@classmethod
を使用する最大の理由は、継承を目的とした代替コンストラクターにあります。これは、ポリモーフィズムで非常に役立ちます。例:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
@classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
Shape
はクラスメソッドfrom_square
を定義する抽象クラスであることに注意してください。Shape
は実際には定義されていないため、Square
から派生する方法がわからないため、単にクラスのデフォルトインスタンスを返します。
継承されたクラスは、このメソッドの独自のバージョンを定義できます。
class Square(Shape):
def __init__(self, side=10):
self.side = side
@classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
@classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
@classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
使用法により、これらのインスタンス化されていないクラスをすべて多態的に扱うことができます
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
これはあなたが言うかもしれない素晴らしいことですが、なぜ私は@staticmethod
としてこの同じ多態的な振る舞いを達成するのに使えなかったのでしょうか:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@staticmethod
def from_square(square):
return Circle(radius=square.length/2)
答えは可能ですが、メソッドでCircle
を明示的に呼び出す必要があるため、継承のメリットは得られません。つまり、オーバーライドせずに継承クラスから呼び出すと、毎回Circle
を取得することになります。
実際にfrom_squareロジックをまったく持たない別のシェイプクラスを定義すると、何が得られるかに注目してください。
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
ここで、@classmethod
を未定義のままにしておくと、cls
が誰であるかを保持しながらShape.from_square
のロジックを使用し、適切な形状を返します。
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)