Pythonの「クラスメソッド」および「インスタンスメソッド」とは何ですか?


37

質問に関連するチャットでの質問があり(質問自体はこの質問とは無関係です)、Pythonをまったく知らないかもしれないことが明らかになりました。

私の考えでは、用語は言語によって異なりますが、一般的に機能を次のように分類できます。

  • [無料]機能
  • 静的メソッド/静的メンバー関数
  • 非静的メソッド/非静的メンバー関数

どうやらPythonには、上記のカテゴリに当てはまらない別の種類の関数があります。それはメソッドですが、「そのクラスを知りません」。

Pythonの「クラスメソッド」と「インスタンスメソッド」とは何ですか?


1
チャットのディスカッションに興味がある人は、ここから始めてください:chat.stackexchange.com/transcript/message/26479002#26479002
yannis

1
IMO良い答えが異なるstackexchangeのウェブサイトで提供されていますstackoverflow.com/questions/136097/...
トレバー・ボイド・スミス

参考までに、リンクは承認済みの下部に表示されます...しかし、多くの人がリンクを見逃したり、リンクに到達したりしないと思うので、ここにコピーしました。
トレバーボイドスミス

回答:


49

短い答え

  • インスタンスメソッドは、そのインスタンス(およびそれから、そのクラス)を知っています
  • クラスメソッドはそのクラスを知っています
  • 静的メソッドはそのクラスまたはインスタンスを知りません

長い答え

クラスメソッド

クラスメソッドは、全体としてのクラスに属するものです。インスタンスは必要ありません。代わりに、クラスは最初の引数として自動的に送信されます。クラスメソッドは、@classmethodデコレータで宣言されます。

例えば:

class Foo(object):
    @classmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"

インスタンスメソッド

一方、インスタンスメソッド それを呼び出すためにインスタンスを必要とし、デコレータを必要としません。これは、最も一般的なタイプの方法です。

class Foo(object):
    def hello(self):
        print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'

(注:上記はpython3の場合です; python2の場合、わずかに異なるエラーが発生します)

静的メソッド

静的メソッドは、クラスメソッドと同様であるが、自動パラメータとしてクラスオブジェクトを取得しないであろう。@staticmethodデコレータを使用して作成されます。

class Foo(object):
    @staticmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)

Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'

ドキュメントリンク

関連するpython3ドキュメントへのリンクは次のとおりです。

データモデルのマニュアルには、これはクラスメソッドと静的メソッドの違いについて言いたいことがあります。

静的メソッドオブジェクト静的メソッドオブジェクトは、関数オブジェクトから上記のメソッドオブジェクトへの変換を無効にする方法を提供します。静的メソッドオブジェクトは、他のオブジェクト(通常はユーザー定義のメソッドオブジェクト)のラッパーです。静的メソッドオブジェクトがクラスまたはクラスインスタンスから取得される場合、実際に返されるオブジェクトはラップされたオブジェクトであり、これ以上の変換は行われません。静的メソッドオブジェクト自体は呼び出し可能ではありませんが、通常、ラップするオブジェクトは呼び出し可能です。静的メソッドオブジェクトは、組み込みのstaticmethod()コンストラクターによって作成されます。

クラスメソッドオブジェクト クラスメソッドオブジェクトは、静的メソッドオブジェクトと同様に、オブジェクトがクラスおよびクラスインスタンスから取得される方法を変更する別のオブジェクトのラッパーです。このような取得時のクラスメソッドオブジェクトの動作は、上記の「ユーザー定義メソッド」で説明されています。クラスメソッドオブジェクトは、組み込みのclassmethod()コンストラクターによって作成されます。

関連する質問


4
@LightnessRacesinOrbit:私は静的メソッドがPythonで特に頻繁に使用されるとは思わない。システムをランダムなサンプルとして使用して、インストールしたすべてのパッケージを検索すると、すべてのメソッドの約1%のみが静的メソッドです(率直に言って、予想以上でした)。
ブライアンオークリー

1
「静的メソッド」は通常コードの匂いであり、Gogole Pythonスタイルガイドなどでは推奨されていません。
9000

3
サブメソッドに注意を向けると、答えがより良いと思います。サブメソッドは、クラスメソッドが有用性を得る場所です。
ウィンストンイーバート

1
@ user2357112:のすべてのインスタンスをカウントしてから"^ def("、のすべてのインスタンスをカウントしました@staticmethod。非常に非科学的ですが、おそらく球場内にありました。
ブライアンオークリー

2
@Kashyap:TL; DRは最初の段落に適用されます。私はそれが下よりも上でうまく機能すると思います。
ブライアンオークリー

8

Pythonの「クラスメソッド」および「インスタンスメソッド」とは何ですか?

  • 「インスタンスメソッド」は、インスタンスに含まれる情報を使用して、どの値を返す(またはどの副作用を行う)かを判断します。これらは非常に一般的です。

  • 「クラスメソッド」は、クラスの情報(そのクラスのインスタンスではなく)を使用して、その動作に影響を与えます(通常、代替インスタンスとして新しいインスタンスを作成するために使用されるため、あまり一般的ではありません)。

  • 「静的メソッド」は、クラスまたはインスタンスに関する情報を使用して、その動作を計算しません。通常は、便宜上クラスに含まれています。(したがって、これらはあまり一般的でもありません。)

Xの関数

数学クラス、「yはxの関数f(x)ですか?」コードでそれを適用しましょう:

y = function(x)

上記のことは、変更されるx可能性があるため、y変更されるとx変更される可能性があることを意味しています。私たちは「と言うとき、これは何を意味するかであるyの関数ですx

何をされますy際にもzありますか12'FooBarBaz'

yはの関数ではないzため、z何でもかまいませんfunctionが、純粋な関数であると仮定すると、関数の結果に影響を与えません。(zグローバル変数としてアクセスする場合、それは純粋な関数ではありません-これは関数の純粋さを意味します。)

次の説明を読むときは、上記のことに留意してください。

インスタンスメソッド

インスタンスメソッドは、インスタンスの関数ある関数です。関数はインスタンスを引数として暗黙的に受け入れ、インスタンスは関数の出力を決定するために関数によって使用されます。

インスタンスメソッドの組み込み例はstr.lowerです。

>>> 'ABC'.lower()
'abc'

str.lower 文字列のインスタンスで呼び出され、インスタンスに含まれる情報を使用して、どの新しい文字列を返すかを判断します。

クラスメソッド:

Pythonでは、すべてがオブジェクトであることに注意してください。つまり、クラスはオブジェクトであり、関数への引数として渡すことができます。

クラスメソッドは、関数である関数であるクラス。クラスを引数として受け入れます。

組み込みの例はdict.fromkeys次のとおりです。

>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}

関数はそれ自身のクラスを暗黙的に知っており、関数はクラスを使用して関数の出力に影響を与え、反復可能からそのクラスの新しいクラスを作成します。同じメソッドを使用する場合、OrderedDictはこれを示します。

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])

クラスメソッドは、そのクラスのインスタンスではなく、クラスに関する情報を使用して、返されるクラスのタイプに影響を与えます。

静的メソッド

「クラスを知らない」メソッドに言及します-これはPythonの静的メソッドです。クラスオブジェクトに便宜上添付されているだけです。オプションで別のモジュールの別の関数にすることもできますが、その呼び出しシグネチャは同じです。

静的メソッドは、クラスでもオブジェクトでもない関数です。

静的メソッドの組み込み例は、Python 3のstr.maketransです。

>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}

いくつかの引数が与えられると、クラスの関数ではない辞書を作成します。

strグローバル名前空間で常に利用可能であるため便利であり、translate関数で簡単に使用できます。

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Python 2では、stringモジュールからアクセスする必要があります。

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'

class AClass(object):
    """In Python, a class may have several types of methods: 
    instance methods, class methods, and static methods
    """

    def an_instance_method(self, x, y, z=None):
        """this is a function of the instance of the object
        self is the object's instance
        """
        return self.a_class_method(x, y)

    @classmethod
    def a_class_method(cls, x, y, z=None):
        """this is a function of the class of the object
        cls is the object's class
        """
        return cls.a_static_method(x, y, z=z)

    @staticmethod
    def a_static_method(x, y, z=None):
        """this is neither a function of the instance or class to 
        which it is attached
        """
        return x, y, z

インスタンス化しましょう:

>>> instance = AClass()

これで、インスタンスはすべてのメソッドを呼び出すことができます。

>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)

ただし、クラスは通常、インスタンスメソッドを呼び出すことを意図していませんが、他のメソッドを呼び出すことが期待されています。

>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'

インスタンスメソッドを呼び出すには、インスタンスを明示的に渡す必要があります。

>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)

「これはPythonの静的メソッドです。単にクラスオブジェクトに便宜上添付されています。オプションで別のモジュールの別の関数にすることもできますが、呼び出しシグネチャは同じです。」便利というよりも混乱しているようです。本体にクラスの概念がないのに、なぜクラスに関数をアタッチするのでしょうか。
モニカと明度レース

@LightnessRacesinOrbit各ポイントについて詳しく説明しました
アーロンホール

個人的に、私がいつも見てきた方法は、インスタンスメソッドは特定のインスタンスに対する操作であり、クラスメソッドは一種のコンストラクターであり(便宜上、MyClass(1,2,3)代わりに似たようなものではありませんMyClass.get_special(1,2,3))、静的メソッドは単なるとにかく独立できる通常の機能です。
Zizouz212

はい、クラスメソッドは通常、代替コンストラクターに使用されます(上記のdict.fromkeysの例を参照してください。pandas.DataFrameのソースコードも参照してください)が、それは定義的な特性ではありません。インスタンスにアクセスせずに、メソッドからクラスレベルで格納されているデータにアクセスするだけでよい場合があります。type(self)(または、さらに悪いことにself .__ class__)を呼び出しており、インスタンスメソッドでselfを直接使用していない場合、それをクラスメソッドと見なす必要があります。クラスメソッドはインスタンスを必要としないため、ユニットテストが容易になります。
アーロンホール

4
  • 「インスタンスメソッド」とは、インスタンスオブジェクトを最初のパラメーターとして渡すメソッドのことで、慣例によりと呼ばれselfます。これがデフォルトです。

  • 「静的メソッド」は、初期selfパラメーターのないメソッドです。これは@staticmethodデコレータで実装されます。

  • 「クラスメソッド」とは、初期パラメーターがインスタンスオブジェクトではなく、クラスオブジェクト(「クラスオブジェクト」とはPythonドキュメントのこの部分を参照)であるメソッドであり、慣習的に呼ばれclsます。これは@classmethodデコレータで実装されます。

C / C ++ / etcの「静的メソッド」という用語の一般的な使用法は、Pythonの「静的」メソッドとPython「クラス」メソッドの両方に適用されます。C / C ++ / etcでは、メソッドは通常、クラスのすべての非インスタンスメンバ/メソッドに暗黙的にアクセスできます。このため、この区別はPython / Ruby / etcなどの言語でのみ存在するのでしょう。


C / C ++の静的メソッドには、クラスオブジェクトへの参照がありますか?それともクラスの「メンバー」ですか?クラスの新しいメンバーを作成できますか?:)
アーロンホール

3
@AaronHall C / C ++には、クラスオブジェクトのようなものはなく、静的メソッドを呼び出すためにそれを参照する必要はありません。書くだけでClass::staticMethod()それで終わりstaticMethod()です(プライベートまたは何かであるために呼び出すことを禁じられていない限り)。
Ixrec
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.