Jaki jest cel jaźni?

Jaki jest cel self słowa w Pythonie? Rozumiem, że odnosi się do konkretnego obiektu utworzonego z tej klasy, ale nie rozumiem, dlaczego musi być dodany do każdej funkcji jako parametr. Aby zilustrować, w Ruby mogę to zrobić:

class myClass
    def myFunc(name)
        @name = name
    end
end
Co rozumiem, dość łatwo. Jednak w Pythonie muszę dołączyć self:
class myClass:
    def myFunc(self, name):
        self.name = name
Czy ktoś może mi to powiedzieć? Nie jest to coś, na co natknąłem się w moim (co prawda ograniczonym) doświadczeniu.
Author: kmario23, 2010-04-26

19 answers

Powodem, dla którego musisz użyć self. jest to, że Python nie używa składni @ do odwoływania się do atrybutów instancji. Python zdecydował się wykonać metody w sposób, który sprawia, że instancja, do której należy metoda, będzie przekazywanaautomatycznie, ale nie otrzymywana automatycznie: pierwszym parametrem metod jest instancja, na której jest wywoływana metoda. To sprawia, że metody są CAŁKOWICIE takie same jak funkcje, i pozostawia rzeczywistą nazwę do wykorzystania do ciebie (chociaż self jest konwencją, a Ludzie na ogół marszczą na Ciebie brwi, gdy używasz czegoś innego.) self nie jest wyjątkowy dla kodu, to po prostu kolejny obiekt.

Python mógł zrobić coś innego, aby odróżnić normalne nazwy od atrybutów-specjalna składnia, taka jak Ruby, lub wymagająca deklaracji, takich jak C++ i Java, a może coś jeszcze innego-ale tak się nie stało. Python służy do tego, aby wszystko było jasne, co jest czym, i chociaż nie robi tego wszędzie wszędzie, robi to na przykład atrybuty. Dlatego przypisanie do atrybutu instancji musi wiedzieć, do której instancji przypisać, i dlatego potrzebuje self..

 600
Author: Thomas Wouters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-27 23:01:28

Weźmy prostą klasę wektorową:

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

Chcemy mieć metodę, która oblicza długość. Jak by to wyglądało, gdybyśmy chcieli zdefiniować to wewnątrz klasy?

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

Jak powinna ona wyglądać, gdy mamy ją zdefiniować jako globalną metodę / funkcję?

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

Więc cała struktura pozostaje taka sama. Jak mogę z tego skorzystać? Jeśli założymy przez chwilę, że nie napisaliśmy metody length dla naszej klasy Vector, możemy zrobić to:

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

To działa, ponieważ pierwszy parametr length_global może być ponownie użyty jako parametr self w length_new. Nie byłoby to możliwe bez wyraźnego self.


Innym sposobem zrozumienia potrzeby jawnego self jest sprawdzenie, gdzie Python dodaje trochę cukru składniowego. Kiedy masz na uwadze, że w zasadzie, połączenie jak

v_instance.length()

Jest wewnętrznie przekształcane do

Vector.length(v_instance)

Łatwo zobaczyć, gdzie self pasuje. Nie piszesz metody instancji w Pythonie; to, co piszesz, to metody klas, które muszą przyjmować instancję jako pierwszy parametr. W związku z tym, będziesz musiał umieścić parametr instancji gdzieś jawnie.

 386
Author: Debilski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-15 06:40:38

Załóżmy, że masz klasę ClassA, która zawiera metodę methodA zdefiniowaną jako:

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

I ObjectA jest instancją tej klasy.

Teraz, gdy ObjectA.methodA(arg1, arg2) jest wywołane, python wewnętrznie konwertuje go dla Ciebie jako:

ClassA.methodA(ObjectA, arg1, arg2)

Zmienna self odnosi się do samego obiektu.

 292
Author: Arjun Sreedharan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-18 16:10:51

Gdy obiekty są utworzone, sam obiekt jest przekazywany do parametru self.

Tutaj wpisz opis obrazka

Z tego powodu DANE obiektu są powiązane z obiektem. Poniżej znajduje się przykład wizualizacji danych każdego obiektu. Zauważ, jak 'self' jest zastępowany nazwą obiektów. Nie mówię, że poniższy przykładowy diagram jest całkowicie dokładny, ale mam nadzieję, że służy celowi w wizualizacji użycia siebie.

Tutaj wpisz opis obrazka

Obiekt jest przekazywane do parametru self tak, że obiekt może przechowywać własne dane.

Chociaż może to nie być do końca dokładne, pomyśl o procesie tworzenia instancji obiektu w taki sposób: gdy obiekt jest tworzony, używa klasy jako szablonu dla własnych danych i metod. Bez przeniesienia własnej nazwy do parametru self, atrybuty i metody w klasie pozostaną ogólnym szablonem i nie będą odwoływane do obiektu (należą do niego). Więc podając nazwę obiektu do parametru self oznacza to, że jeżeli z jednej klasy zostanie utworzonych 100 obiektów, wszystkie mogą śledzić własne dane i metody.

Zobacz ilustrację poniżej:

Tutaj wpisz opis obrazka

 157
Author: sw123456,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-28 05:47:02

Podoba mi się ten przykład:

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: []
 65
Author: kame,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-26 16:02:48

Zademonstruję kodem, że nie używa klas :

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'

Klasy są po prostu sposobem na uniknięcie przechodzenia przez ten" stan " cały czas (i inne miłe rzeczy, takie jak inicjalizacja, skład klas, rzadko potrzebne metaklasy i wspieranie niestandardowych metod do nadpisywania operatorów).

Teraz zademonstrujmy powyższy kod przy użyciu wbudowanej maszyny klasy python, aby pokazać, że jest to zasadniczo to samo.

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 )

[Przenieś moją odpowiedź z duplicate pytanie zamknięte]

 33
Author: ninjagecko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-22 00:27:23

Jak również wszystkie inne powody już podane, pozwala na łatwiejszy dostęp do nadpisanych metod; można wywołać Class.some_method(inst).

Przykład, gdzie jest przydatny:

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
Author: Ponkadoodle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-24 22:23:49

Poniższe fragmenty pochodzą z dokumentacji Pythona O self:

Podobnie jak w Modula-3, nie ma skrótów [w Pythonie] do odwoływania się do członków obiektu z jego metod: funkcja metody jest deklarowana z jawnym pierwszym argumentem reprezentującym obiekt, który jest dostarczany domyślnie przez wywołanie.

Często pierwszy argument metody nazywa się self. To nic innego jak Konwencja: nazwa jaźń nie ma absolutnie żadnego specjalnego znaczenie dla Pythona. Zauważ jednak, że nie przestrzegając konwencji Twój kod może być mniej czytelny dla innych programistów Pythona, i jest również możliwe, że napisany zostanie program do przeglądania klas, który opiera się na takiej konwencji.

Więcej informacji można znaleźć w samouczku dokumentacji Pythona na temat klas .

 16
Author: Matthew Rankin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-26 14:09:29

Python nie jest językiem zbudowanym do programowania obiektowego w przeciwieństwie do Javy czy C++.

Podczas wywoływania statycznej metody w Pythonie, po prostu pisze się metodę z regularnymi argumentami wewnątrz niej.

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

Jednak metoda obiektowa, która wymaga utworzenia zmiennej, która jest zwierzęciem, w tym przypadku, wymaga argumentu self

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

Metoda self jest również używana do odwoływania się do pola zmiennej w klasie.

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


    def getAnimalName(self):
        return self.animalName

W tym przypadku self odnosi się do animalName zmienna całej klasy. Pamiętaj: jeśli masz zmienną w metodzie, self nie będzie działać. Ta zmienna istnieje tylko wtedy, gdy ta metoda jest uruchomiona. Do definiowania pól (zmiennych całej klasy) należy zdefiniować je poza metodami klasy.

Jeśli nie rozumiesz ani jednego słowa z tego, co mówię, to Google " programowanie obiektowe."Kiedy to zrozumiesz, nie będziesz musiał nawet zadawać tego pytania :).

 11
Author: ytpillai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 18:39:06

Jego użycie jest podobne do użycia słowa kluczowego this w Javie, tzn. do podania odniesienia do bieżącego obiektu.

 10
Author: Gaurav Nishant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-27 09:47:48

Jest tam, aby podążać za Pythonowym zen "explicit is better than implicit". To rzeczywiście odniesienie do Twojego obiektu klasowego. Na przykład w Javie i PHP nazywa się this.

Jeśli user_type_name jest polem w twoim modelu, uzyskujesz do niego dostęp przez self.user_type_name.

 7
Author: dan-klasson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-24 22:24:58

self jest obiektem odniesienia do samego obiektu, dlatego są one takie same. Metody Pythona nie są wywoływane w kontekście samego obiektu. self w Pythonie mogą być używane do obsługi niestandardowych modeli obiektowych lub czegoś takiego.

 4
Author: Ming-Tang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-25 20:26:35

Dziwię się, że nikt nie wspomniał o Lua. Lua używa również zmiennej' self', jednak można ją pominąć, ale nadal używać. C++ robi to samo z 'this'. Nie widzę powodu, aby deklarować 'self' w każdej funkcji, ale nadal powinieneś być w stanie używać go tak, jak możesz z lua i C++. Dla języka, który szczyci się zwięzłością, dziwne jest to, że wymaga deklaracji zmiennej self.

 3
Author: user441521,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-12 18:10:32

To dlatego, że przy okazji python jest zaprojektowany alternatywy raczej nie będą działać. Python został zaprojektowany, aby umożliwić definiowanie metod lub funkcji w kontekście, w którym zarówno implicit this (A-La Java/C++), jak i explicit @ (A-la ruby) nie będą działać. Weźmy przykład z explicit approach z konwencjami Pythona:

def fubar(x):
    self.x = x

class C:
    frob = fubar

Teraz funkcja fubar nie będzie działać, ponieważ zakłada, że self jest zmienną globalną (a także w frob). Alternatywą byłoby wykonanie metoda ma zastąpiony globalny zakres (gdzie {[6] } jest obiektem).

Implicit podejście będzie

def fubar(x)
    myX = x

class C:
    frob = fubar

Oznaczałoby to, że myX będzie interpretowana jako zmienna lokalna w fubar (a także w frob). Alternatywą w tym przypadku byłoby wykonywanie metod z zastąpionym lokalnym zakresem, który jest zachowany między wywołaniami, ale to usunie możliwość zmiennych lokalnych metody.

Jednak obecna sytuacja działa dobrze:

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

 class C:
     frob = fubar

Tutaj, gdy wywołana jako metoda frob otrzyma obiekt, na którym jest wywołana poprzez parametr self, a fubar może być wywołana z obiektem jako parametrem i działa tak samo (to jest tak samo jak C.frob myślę).

 2
Author: skyking,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 07:31:02

Po pierwsze, self jest konwencjonalną nazwą, można umieścić w jej miejsce cokolwiek innego (będąc spójnym).

Odnosi się do samego obiektu, więc kiedy go używasz, deklarujesz, że. name i .wiek to właściwości obiektów uczniowskich (uwaga, a nie Klasy uczniowskiej), które zamierzasz utworzyć.

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

Kod jest tutaj

 2
Author: harrypotter0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-12 04:45:25

W metodzie __init__ self odnosi się do nowo utworzonego obiektu; w innych metodach klasy odnosi się do instancji, której metoda została wywołana.

Ja, jako imię, jest tylko zjazd, nazywaj to jak chcesz ! ale używając go, na przykład do usunięcia obiektu, musisz użyć tej samej nazwy: __del__(var), Gdzie var zostało użyte w __init__(var,[...])

Należy również spojrzeć na cls, aby mieć the bigger picture. To post to może być pomocne.

 1
Author: TheEnglishMe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:30

Spójrz na poniższy przykład, który jasno wyjaśnia cel 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 jest używany/potrzebny do rozróżniania instancji.

 1
Author: kmario23,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-15 07:54:27

Użycie argumentu, konwencjonalnie zwanego self nie jest tak trudne do zrozumienia, dlaczego jest to konieczne? Albo dlaczego wyraźnie o tym wspomnieć? To, jak sądzę, jest większe pytanie dla większości użytkowników, którzy szukają tego pytania, a jeśli nie, z pewnością będą mieli to samo pytanie, ponieważ posuwają się do przodu ucząc się Pythona. Polecam im przeczytać te kilka blogów:

1: Użycie self explained

Zauważ, że nie jest to słowo kluczowe.

Pierwszy argument każdej metody klasy, włączając init, jest zawsze odniesieniem do bieżącej instancji klasy. Zgodnie z konwencją argument ten jest zawsze nazywany self. W metodzie INIT self odnosi się do nowo utworzonego obiektu; w innych metodach klasy odnosi się do instancji, której metoda została wywołana. Na przykład poniższy kod jest taki sam jak powyższy kod.

2: Dlaczego mamy to w ten sposób i dlaczego nie możemy go wyeliminować jako argument, jak Java, i mieć słowo kluczowe zamiast

Kolejną rzeczą, którą chciałbym dodać jest to, że opcjonalny argument self pozwala mi deklarować statyczne metody wewnątrz klasy, nie pisząc self.

Przykłady kodu:

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 : to działa tylko w Pythonie 3.x.

W poprzednich wersjach, musisz jawnie dodać @staticmethod dekorator, w przeciwnym razie self argument jest obowiązkowy.

 1
Author: Bugs Buggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-12 10:20:06

Jest to jawne odniesienie do obiektu instancji klasy.

 -2
Author: SilentGhost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-25 20:24:57