web-dev-qa-db-ja.com

クラスメソッドをインスタンスからメソッドとして呼び出すのは悪い形式ですか?

例.

私がこのようなものを持っている場合:

class C(object):
    @classmethod
    def f(cls, x):
       return x + x

これは機能します:

c = C()

c.f(2)
4

しかし、それは悪い形ですか?電話するだけでいい

C.f()

または

c.__class__.f()

明らかに、これは、fがクラスであることを期待してself/clsと相互作用しない場合にのみ意味があります。

38
Josh Gibson

インスタンスからクラスメソッドを呼び出したい場合は、おそらくクラスメソッドは必要ありません。

この例では、最後の発言(self/clsの相互作用がない)のために、静的メソッドを指定した方が適切です。

class C(object):
    @staticmethod
    def f(x):
       return x + x

このように、両方を行うのは「良い形」です

c = C()
c.f(2)

そして

C.f(2)
31
Toni Ruža

クラスの外部からこのようなクラスメソッドを使用したことを思い出しませんが、インスタンスメソッドがそれ自体でクラスメソッドを呼び出すことは確かに問題ありません(例:self.foo()ここで、fooはクラスメソッドです) 。これにより、継承が期待どおりに機能し、基本クラスではなく適切なサブクラスで.foo()が呼び出されます。

10
Matt Good

それは主に見た目を混乱させるだけです。私があなたのクラスを使っていて、これを見たとしたら、他にどんな驚きがあるのだろうと思うでしょう。それはただ悪いデザインのように見えます。

静的メソッドだけではない理由はありますか?

5
Trey Stout

C.f()c_instance.f()よりも明確であり、c_instance.__class__.f()は単に醜いです。明快さと美しさはpythonコミュニティで非常に愛されている特性なので、C.f()が最良のルートであると言う傾向があります。

他の方法でそれを呼びたいと思う特別な理由はありますか?

3
vezult

すでにCのインスタンスがある場合、なぜf()がクラスメソッドである必要があるのですか?それは悪い形式であるだけでなく、通常は必要ありません。ネット上の誰かが言います: "オブジェクト内のいくつかのインスタンス変数が使用されているという印象を与えるため、これは悪いことですが、そうではありません。」

ただし、 learning python の484ページでは、どちらの方法でもメソッドを呼び出すことができ、で同じインスタンスを渡す限り、まったく同じになると記載されています。

3
John Ellinwood

次のような非クラスメソッドからいくつかのクラスメソッド(クラスへの参照を保持するためにクラスメソッドである必要があります)を呼び出していたときに、これに遭遇しました。

class A:
  def a(self, number):
    print("a", self, number)
    self.b(number)

  @classmethod
  def b(cls, number):
    print("b", cls, number + 1)
    cls.c(number)

  @classmethod
  def c(cls, number):
    print("c", cls, number * 2)



b = A()
b.a(3) 

上記のコードは次の結果を生成します。

a <__main__.A object at 0x000001FAC09FE358> 3
b <class '__main__.A'> 4
c <class '__main__.A'> 6

これが最良の規則だと言っているわけではありませんが、Python 3.6では何も壊れません

0
David Culbreth