Python - po co używać „self” w klasie?

82

Czym różnią się te dwie klasy?

class A():
    x=3

class B():
    def __init__(self):
        self.x=3

Czy jest jakaś znacząca różnica?

ryeguy
źródło
6
nie, to nie jest duplikat.
1
@hop: Interesujące stwierdzenie, ale nie podałeś żadnego przykładu ani dowodu, że nie jest to duplikat. Dlaczego to mówisz?
S.Lott,
2
@ S.Lott - co? Drugie pytanie dotyczy tego, dlaczego musimy wyraźnie przekazać siebie. Ten pyta o różnicę, ponieważ zmienne klas i instancji.
Dana,
1
@ S.Lott To nie jest to samo pytanie. Nawet spojrzałem na to, zanim o to zapytałem.
ryeguy
2
@ S.Lott: 68282 to bezużyteczne pytanie o to, dlaczego musisz jawnie stawiać siebie jako pierwszy argument metod; to pytanie dotyczy różnicy między członkami klasy i instancji. S.Lott, bardzo podoba mi się twój wkład w SO, ale tym razem się mylisz.

Odpowiedzi:

137

A.xjest zmienną klasową . Bjest self.xto zmienna przykład .

czyli Ajest xdzielone między wystąpieniami.

Byłoby łatwiej zademonstrować różnicę w czymś, co można zmodyfikować, jak lista:

#!/usr/bin/env python

class A:
    x = []
    def add(self):
        self.x.append(1)

class B:
    def __init__(self):
        self.x = []
    def add(self):
        self.x.append(1)

x = A()
y = A()
x.add()
y.add()
print("A's x:", x.x)

x = B()
y = B()
x.add()
y.add()
print("B's x:", x.x)

Wynik

A's x: [1, 1]
B's x: [1]
Douglas Leeder
źródło
8
Może też opublikuj wyjście swojego skryptu, wtedy można zobaczyć różnicę bez kopiowania i samodzielnego uruchamiania ...
Martin
2
Czy w takim razie jaźń Pythona jest odpowiednikiem Javy? Przepraszam za noobizm, proszę
Jean Azzopardi
2
@Jean - Yes-ish - self musi być zwykłą nazwą nadaną pierwszemu parametrowi metod instancji - a python jawnie przekazuje bieżące wystąpienie metod instancji jako pierwszy argument do metod instancji. Ale robi to samo, co Java
Douglas Leeder
@Jean Azzopardi: self jest prawie jak Java (i c ++) this. Jaźń jest po prostu wymagana; czasami jest to rozumiane przez kompilator Java (innym razem jest to wymagane).
S.Lott,
@Douglas Leeder - nie ma problemu.
UnkwnTech
56

Podobnie jak marginesie: selfto właściwie tylko losowo wybrane słowo, które wykorzystuje wszystkich, ale można też użyć this, foolub myselfczy cokolwiek innego chcesz, to tylko pierwszy parametr każdego non statycznej metody dla klasy. Oznacza to, że słowo selfnie jest konstrukcją językową, ale tylko nazwą:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2
André
źródło
1
Dlaczego jest to odpowiedź, a nie komentarz
Gabriel Petersson
23

Ax jest zmienną klasy i będzie współdzielona we wszystkich wystąpieniach A, chyba że zostanie wyraźnie nadpisana w ramach wystąpienia. Bx jest zmienną instancji, a każda instancja B ma swoją własną wersję.

Mam nadzieję, że poniższy przykład Pythona może wyjaśnić:


    >>> class Foo():
    ...     i = 3
    ...     def bar(self):
    ...             print 'Foo.i is', Foo.i
    ...             print 'self.i is', self.i
    ... 
    >>> f = Foo() # Create an instance of the Foo class
    >>> f.bar()
    Foo.i is 3
    self.i is 3
    >>> Foo.i = 5 # Change the global value of Foo.i over all instances
    >>> f.bar()
    Foo.i is 5
    self.i is 5
    >>> f.i = 3 # Override this instance's definition of i
    >>> f.bar()
    Foo.i is 5
    self.i is 3
TerrorBite
źródło
17

Tłumaczyłem to na tym przykładzie

# By TMOTTM

class Machine:

    # Class Variable counts how many machines have been created.
    # The value is the same for all objects of this class.
    counter = 0

    def __init__(self):

        # Notice: no 'self'.
        Machine.counter += 1

        # Instance variable.
        # Different for every object of the class.
        self.id = Machine.counter

if __name__ == '__main__':
    machine1 = Machine()
    machine2 = Machine()
    machine3 = Machine()

    #The value is different for all objects.
    print 'machine1.id', machine1.id
    print 'machine2.id', machine2.id
    print 'machine3.id', machine3.id

    #The value is the same for all objects.
    print 'machine1.counter', machine1.counter
    print 'machine2.counter', machine2.counter
    print 'machine3.counter', machine3.counter

Wyjście będzie wtedy

machine1.id 1
machine2.id 2
machine3.id 3

maszyna 1. licznik 3
maszyna 2. licznik 3
machine3.counter 3
TMOTTM
źródło
3

Dopiero co zacząłem uczyć się języka Python i przez pewien czas to też mnie zdezorientowało. Próbując dowiedzieć się, jak to wszystko ogólnie działa, wymyśliłem ten bardzo prosty fragment kodu:

# Create a class with a variable inside and an instance of that class
class One:
    color = 'green'

obj2 = One()


# Here we create a global variable(outside a class suite).
color = 'blue'         

# Create a second class and a local variable inside this class.       
class Two:             
    color = "red"

    # Define 3 methods. The only difference between them is the "color" part.
    def out(self):     
        print(self.color + '!')

    def out2(self):
        print(color + '!')

    def out3(self):
        print(obj2.color + '!')

# Create an object of the class One
obj = Two()

Kiedy dzwonimy out(), otrzymujemy:

>>> obj.out()

red!

Kiedy dzwonimy out2():

>>> obj.out2()

blue!

Kiedy dzwonimy out3():

>>> obj.out3()

green!

Tak więc w pierwszej metodzie selfokreśla, że ​​Python powinien używać zmiennej (atrybutu), która „należy” do utworzonego przez nas obiektu klasy, a nie globalnego (poza klasą). Więc używa color = "red". W metodzie Python niejawnie podstawia selfnazwę utworzonego przez nas obiektu ( obj). self.coloroznacza „otrzymuję color="red"zobj

W drugiej metodzie nie ma selfwskazania obiektu, z którego ma być pobrany kolor, więc dostajemy kolor globalny color = 'blue'.

W trzeciej metodzie zamiast tego selfużyliśmy obj2- nazwa innego obiektu do pobrania color. Dostaje color = 'green'.

yabee-dabee
źródło