web-dev-qa-db-ja.com

自己の目的は何ですか?

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

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

これはごく簡単にわかります。しかし、Pythonではselfを含める必要があります。

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

誰もがこれを通して私に話すことができますか?それは私の(確かに限られた)経験で出会ったことではありません。

985
richzilla

self.を使用する必要があるのは、Pythonが@構文を使用してインスタンス属性を参照しないためです。 Pythonは、メソッドが属するインスタンスをpassedに自動化するが、receivedに自動化しない方法でメソッドを実行することを決定しました。 methodsは、メソッドが呼び出されるインスタンスです。これにより、メソッドは関数とまったく同じになり、使用する実際の名前はあなたに任されます(ただし、selfが慣習であり、他の何かを使用すると一般的に人々はあなたに眉をひそめます。)selfはコードにとって特別なものではなく、単なる別のオブジェクトです。

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

662
Thomas Wouters

単純なベクトルクラスを見てみましょう:

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の最初のパラメータがlength_newselfパラメータとして再利用できるのでうまくいきます。これは明示的なselfがなければ不可能です。


明示的なselfの必要性を理解するもう1つの方法は、Pythonがどこに構文糖を追加したかを調べることです。あなたが心に留めておくと、それは基本的に、のような呼び出し

v_instance.length()

内部的にに変換されます

Vector.length(v_instance)

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

396
Debilski

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

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

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

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

ClassA.methodA(ObjectA, arg1, arg2)

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

335

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

enter image description here

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

enter image description here

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

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

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

enter image description here

188
sw123456

私はこの例が好きです:

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: []
71
kame

はクラスを使わない

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 )

[重複した質問から回答を移行しました]

34
ninjagecko

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

Modula-3のように、そのメソッドからオブジェクトのメンバを参照するための略語はありません。メソッド関数は、オブジェクトを表す明示的な最初の引数で宣言されます。

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

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

17
Matthew Rankin

すでに述べた他のすべての理由と同様に、オーバーライドされたメソッドへのアクセスを容易にします。 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"
17
Ponkadoodle

その使用方法は、Javaでのthisキーワードの使用方法に似ています。つまり、現在のオブジェクトへの参照を与えるためです。

12
Gaurav Nishant

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は機能しません。その変数は、そのメソッドが実行されている間だけ存在します。フィールド(クラス全体の変数)を定義するには、クラスメソッドの外側でそれらを定義する必要があります。

私が言っていることの1つの単語がわからない場合は、Googleの「Object Oriented Programming」。これを理解すれば、その質問をする必要すらありません:)。

11
ytpillai

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

user_type_nameがあなたのモデルのフィールドであるならば、あなたはself.user_type_nameによってそれにアクセスします。

7
dan-klasson

まず第一に、selfは慣習的な名前であり、その代わりに他の何か(首尾一貫した)を置くことができます。

それはオブジェクト自身を参照するので、あなたがそれを使用しているとき、あなたは.nameと.ageがあなたが作成しようとしているStudentオブジェクトのプロパティであることを宣言しています。

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

コードはこちら

5
Akash Kandpal

selfは、オブジェクト自体へのオブジェクト参照です。したがって、それらは同じです。 Pythonメソッドはオブジェクト自体のコンテキストでは呼び出されません。 Pythonのselfはカスタムオブジェクトモデルか何かを扱うために使われるかもしれません。

5
Ming-Tang

だれもLuaを立ち上げていないのは驚きです。 Luaは 'self'変数も使用しますが、省略することもできますが、まだ使用されています。 C++は、これと同じことを行います。それぞれの関数で 'self'を宣言しなければならない理由はありませんが、luaとC++でできるのと同じようにそれを使用できるはずです。簡潔であることに誇りを持っている言語にとって、それはあなたが自己変数を宣言することを要求することは奇妙です。

4
user441521

Pythonが設計されている方法では、代替手段はほとんど機能しないからです。 Pythonは、暗黙のthis(a-la Java/C++)または明示的な@(a-la Ruby)の両方が機能しないコンテキストでメソッドまたは関数を定義できるように設計されています。 Pythonの規約を使った明示的なアプローチの例を見てみましょう:

def fubar(x):
    self.x = x

class C:
    frob = fubar

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

暗黙のアプローチは、

def fubar(x)
    myX = x

class C:
    frob = fubar

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

しかし、現在の状況はうまくいきます。

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

 class C:
     frob = fubar

ここでメソッドとして呼び出されると、frobselfパラメータを介して呼び出されたオブジェクトを受け取り、fubarはオブジェクトとしてパラメータとして呼び出すことができ、同じように機能します(C.frobと同じです) ).

3
skyking

次の例を見てください。これは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は、インスタンス間を区別するために使用される/必要とされます。

3
kmario23

従来はselfと呼ばれていた引数の使用は、なぜそれが必要なのか、理解するのがそれほど難しくありません。それともなぜそれを明示的に言及するのか?それは、私がこの質問を探すほとんどのユーザーにとってより大きな質問であるか、そうでなければ、彼らはpythonを学ぶのと同じ質問をするでしょう。私は彼らにこれらのブログを読むことを勧めます:

1:自己使用の説明

これはキーワードではありません。

Initを含むすべてのクラスメソッドの最初の引数は、常にクラスの現在のインスタンスへの参照です。慣例により、この引数は常にselfという名前です。 initメソッドでは、selfは新しく作成されたオブジェクトを参照します。他のクラスメソッドでは、メソッドが呼び出されたインスタンスを参照します。例えば、以下のコードは上記のコードと同じです。

2:なぜ私たちはこのようにしているのでしょうか、そしてなぜJavaのようにそれを引数として排除できず、代わりにキーワードを持っているのでしょう

もう1つ追加したいのは、オプションのself引数を使用すると、selfを記述しなくてもクラス内で静的メソッドを宣言できるようになることです。

コード例:

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

    def objectMethod(self):
        print "This is an object method which needs an instance of a class, and that is what self refers to"

_ ps _ :これはPython 3.xでのみ機能します。

以前のバージョンでは、明示的に@staticmethodデコレータを追加する必要があります。それ以外の場合はself引数は必須です。

3
Bugs Buggy

__init__メソッドでは、selfは新しく作成されたオブジェクトを参照します。他のクラスメソッドでは、メソッドが呼び出されたインスタンスを参照します。

selfは、名前として、単なる慣例です。必要に応じて呼び出してください。しかし、それを使うとき、例えばオブジェクトを削除するとき、あなたは同じ名前を使う必要があります:__del__(var)、ここでvar__init__(var,[...])で使われました

全体図を持つには、clsも見てください。この post は役に立ちます。

1
TheEnglishMe

selfname__は避けられません。

questionselfname__は暗黙的または明示的であるべきです。 Guido van Rossum はこの問題を解決し、 selfname__は のままにする必要があると言っています。

ではselfname__はどこに住んでいますか?

もし関数型プログラミングだけに固執すればselfname__は必要ないでしょう。 Python OOPと入力すると、そこにselfname__が見つかります。

これは、メソッドclass Cを持つ典型的なユースケースm1です。

class C:
    def m1(self, arg):
        print(self, ' inside')
        pass

ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address

このプログラムは出力します:

<__main__.C object at 0x000002B9D79C6CC0>  outside
<__main__.C object at 0x000002B9D79C6CC0>  inside
0x2b9d79c6cc0

そのためselfname__はクラスインスタンスのメモリアドレスを保持します。 selfname__の目的は、インスタンスメソッドの参照を保持し、その参照への 明示的 アクセスを持つことになります。


クラスメソッドには3つの異なるタイプがあります。

  • 静的メソッド(read:functions)
  • クラスメソッド
  • インスタンスメソッド(前述).
0
prosti