1254

selfPythonの単語の目的は何ですか? そのクラスから作成された特定のオブジェクトを参照していることは理解していますが、すべての関数にパラメーターとして明示的に追加する必要がある理由がわかりません。たとえば、Ruby では次のことができます。

class myClass
    def myFunc(name)
        @name = name
    end
end

私はそれを非常に簡単に理解しています。ただし、Python では以下を含める必要がありますself

class myClass:
    def myFunc(self, name):
        self.name = name

誰か私にこれについて話してもらえますか? それは、私の (確かに限られた) 経験の中で出会ったものではありません。

4

26 に答える 26

761

使用する必要がある理由は、Python が構文をself.使用してインスタンス属性を参照しないためです。@Python は、メソッドが属するインスタンスを自動的に渡すが、自動的に受け取らないようにする方法でメソッドを実行することにしました。メソッドの最初のパラメーターは、メソッドが呼び出されるインスタンスです。これにより、メソッドは関数とまったく同じになり、実際の名前を使用するのはあなた次第です (ただし、これselfは慣例であり、他のものを使用すると人々は一般的に眉をひそめます)。selfこれはコードにとって特別なものではなく、単なる別のオブジェクトです。 .

Python は通常の名前と属性を区別するために別のことをすることもできたでしょう -- Ruby のような特別な構文や、C++ や Java のような宣言の要求、あるいはもっと違うことをするかもしれませんが、そうしませんでした。Python は物事を明確にするためのものであり、何が何であるかを明確にするためのものです。すべての場所でそれを行うわけではありませんが、インスタンスの属性に対しては行います。そのため、インスタンス属性への割り当てでは、割り当て先のインスタンスを知る必要があり、それが必要な理由self.です。

于 2010-04-25T20:25:37.537 に答える
548

次のように定義されClassAたメソッドを含むクラスがあるとします。methodA

def methodA(self, arg1, arg2):
    # do something

そしてObjectA、このクラスのインスタンスです。

ObjectA.methodA(arg1, arg2)が呼び出されると、python は内部的に次のように変換します。

ClassA.methodA(ObjectA, arg1, arg2)

self変数はオブジェクト自体を参照します。

于 2014-01-26T17:31:58.857 に答える
434

単純なベクトル クラスを考えてみましょう。

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

長さを計算するメソッドが必要です。クラス内で定義したい場合、どのように見えるでしょうか?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

それをグローバルなメソッド/関数として定義するとしたら、どのように見えるべきでしょうか?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

したがって、全体の構造は同じままです。これをどのように活用できますか?lengthクラスのメソッドを書いていないと仮定すると、次のようにするVectorことができます。

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

これは、 の最初のパラメータがのパラメータlength_globalとして再利用できるため機能します。これは、明示的な なしでは不可能です。selflength_newself


明示的な必要性を理解するもう 1 つの方法はself、Python が構文糖衣を追加する場所を確認することです。心に留めておくと、基本的には次のような呼び出しです

v_instance.length()

内部的に変換されます

Vector.length(v_instance)

実際に Python でインスタンス メソッドを作成するわけではselfありません。あなたが書くのは、最初のパラメータとしてインスタンスを取る必要があるクラスメソッドです。したがって、インスタンス パラメータを明示的にどこかに配置する必要があります。

于 2010-04-28T00:03:33.760 に答える
239

オブジェクトがインスタンス化されると、オブジェクト自体が self パラメーターに渡されます。

ここに画像の説明を入力

このため、オブジェクトのデータはオブジェクトにバインドされます。以下は、各オブジェクトのデータがどのように見えるかを視覚化する方法の例です。「self」がオブジェクト名に置き換えられていることに注意してください。以下のこの例の図が完全に正確であると言っているわけではありませんが、self の使用を視覚化する目的に役立つことを願っています。

ここに画像の説明を入力

オブジェクトが自身のデータを保持できるように、オブジェクトは self パラメータに渡されます。

これは完全に正確ではないかもしれませんが、オブジェクトをインスタンス化するプロセスを次のように考えてみてください。オブジェクトが作成されると、オブジェクトはクラスを独自のデータとメソッドのテンプレートとして使用します。それ自身の名前を self パラメーターに渡さないと、クラスの属性とメソッドは一般的なテンプレートとして残り、オブジェクトに参照 (所属) されません。そのため、オブジェクトの名前を self パラメータに渡すことで、1 つのクラスから 100 個のオブジェクトがインスタンス化された場合、それらすべてが独自のデータとメソッドを追跡できることを意味します。

以下の図を参照してください。

ここに画像の説明を入力

于 2015-06-28T05:47:02.743 に答える
85

私はこの例が好きです:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
于 2010-04-26T16:02:48.360 に答える
45

クラスを使用しないコードでデモンストレーションします。

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

クラスは、この「状態」を常に渡さないようにするための手段にすぎません (また、初期化、クラス構成、めったに必要とされないメタクラス、演算子をオーバーライドするためのカスタム メソッドのサポートなどのその他の優れた機能)。

それでは、組み込みの python クラス機構を使用して上記のコードを示し、基本的に同じことを示しましょう。

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[重複した閉じられた質問から私の回答を移行しました]

于 2011-06-22T00:27:23.557 に答える
23

次の抜粋は、self に関する Python ドキュメントからのものです。

Modula-3 と同様に、[Python では] メソッドからオブジェクトのメンバーを参照する省略表現はありません。メソッド関数は、呼び出しによって暗黙的に提供される、オブジェクトを表す明示的な最初の引数で宣言されます。

多くの場合、メソッドの最初の引数は self と呼ばれます。これは慣例に過ぎません: self という名前は、Python にとって特別な意味はまったくありません。ただし、規則に従わないと、コードが他の Python プログラマーにとって読みにくくなる可能性があることに注意してください。また、そのような規則に依存するクラス ブラウザー プログラムが作成されることも考えられます。

詳細については、クラスに関する Python ドキュメント チュートリアルを参照してください。

于 2010-04-25T20:29:08.607 に答える
22

既に述べた他のすべての理由と同様に、オーバーライドされたメソッドに簡単にアクセスできます。あなたが呼び出すことができますClass.some_method(inst)

便利な場所の例:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"
于 2010-04-25T20:31:43.737 に答える
18

thisその使用法は、Java でのキーワードの使用法に似ています。つまり、現在のオブジェクトへの参照を提供します。

于 2012-08-30T16:37:23.597 に答える
14

Python は、Java や C++ とは異なり、オブジェクト指向プログラミング用に構築された言語ではありません。

Python で静的メソッドを呼び出す場合、通常の引数を内部に持つメソッドを単純に記述します。

class Animal():
    def staticMethod():
        print "This is a static method"

ただし、この場合、Animal である変数を作成する必要があるオブジェクト メソッドには、self 引数が必要です。

class Animal():
    def objectMethod(self):
        print "This is an object method which needs an instance of a class"

self メソッドは、クラス内の変数フィールドを参照するためにも使用されます。

class Animal():
    #animalName made in constructor
    def Animal(self):
        self.animalName = "";


    def getAnimalName(self):
        return self.animalName

この場合、self はクラス全体の animalName 変数を参照しています。注意: メソッド内に変数がある場合、self は機能しません。その変数は、そのメソッドが実行されている間だけ存在します。フィールド (クラス全体の変数) を定義するには、クラス メソッドの外で定義する必要があります。

私が言っていることの一言も理解できない場合は、Google の「オブジェクト指向プログラミング」で検索してください。これを理解すれば、その質問をする必要さえありません:)。

于 2015-05-25T16:04:31.433 に答える
11

これは、Python 禅の「明示的は暗黙的よりも優れている」に従うためにあります。それは確かにあなたのクラスオブジェクトへの参照です。たとえば、Java や PHP では、 と呼ばれthisます。

user_type_nameがモデルのフィールドである場合は、 でアクセスしますself.user_type_name

于 2013-08-16T17:23:12.960 に答える
11

selfオブジェクト自体へのオブジェクト参照であるため、それらは同じです。Python メソッドは、オブジェクト自体のコンテキストでは呼び出されません。 selfPython では、カスタム オブジェクト モデルなどを処理するために使用できます。

于 2010-04-25T20:26:35.897 に答える
7

次の例を見てください。self

class Restaurant(object):  
    bankrupt = False

    def open_branch(self):
        if not self.bankrupt:
           print("branch opened")

#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False

#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True   
>>> y.bankrupt
True

>>> x.bankrupt
False  

selfインスタンスを区別するために使用/必要です。

出典: Python の自己変数の説明 - Pythontips

于 2014-11-15T07:54:27.367 に答える
5

ところで、python が設計されているため、代替手段はほとんど機能しません。thisPython は、暗黙的(Java/C++ 風) または明示的@(Ruby 風) の両方が機能しないコンテキストでメソッドまたは関数を定義できるように設計されています。Python 規則を使用した明示的なアプローチの例を見てみましょう。

def fubar(x):
    self.x = x

class C:
    frob = fubar

それがグローバル変数であると仮定するため、関数は機能しません(そして同様fubarに)。別の方法は、置き換えられたグローバルスコープでメソッドを実行することです(オブジェクトはどこにありますか)。selffrobself

暗黙のアプローチは次のようになります

def fubar(x)
    myX = x

class C:
    frob = fubar

これはmyX、ローカル変数として解釈されることを意味しますfubar(およびfrob同様に)。ここでの代替手段は、呼び出し間で保持される置き換えられたローカルスコープでメソッドを実行することですが、それはメソッドのローカル変数の可能性を取り除きます。

ただし、現在の状況はうまく機能しています。

 def fubar(self, x)
     self.x = x

 class C:
     frob = fubar

ここでメソッドとして呼び出されると、パラメーターfrobを介して呼び出されたオブジェクトを受け取り、オブジェクトをパラメーターとして呼び出して同じように動作させることができます(が思うのと同じです) 。selffubarC.frob

于 2015-08-27T07:31:02.533 に答える
0

これは、クラス インスタンス オブジェクトへの明示的な参照です。

于 2010-04-25T20:24:57.337 に答える
0

少なくとも Python では、self パラメータはプレースホルダーと考えることができます。これを見てください:

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

p1 = Person("John", 36)

print(p1.name)
print(p1.age)

この場合の自己と他の多くは、名前の値を保存すると言う方法として使用されました。ただし、その後、p1 を使用して、使用しているクラスに割り当てます。次に、それを印刷するときに、同じ p1 キーワードを使用します。

これがPythonに役立つことを願っています!

于 2020-06-23T13:50:57.137 に答える