Python - warum "Selbst" in einer Klasse verwenden?

82

Wie unterscheiden sich diese beiden Klassen?

class A():
    x=3

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

Gibt es einen signifikanten Unterschied?

Ryeguy
quelle
6
Nein, es ist kein Duplikat.
1
@hop: Interessante Behauptung, aber Sie haben kein Beispiel oder keinen Beweis dafür geliefert, dass es sich nicht um ein Duplikat handelt. Warum sagst du das?
S.Lott
2
@ S.Lott - Huh? Die andere Frage ist, warum wir uns explizit selbst übergeben müssen. Dieser fragt nach dem Unterschied zwischen Klassen- und Instanzvariablen.
Dana
1
@ S.Lott Das ist nicht die gleiche Frage. Ich habe mir das sogar angesehen, bevor ich es gefragt habe.
Ryeguy
2
@ S.Lott: 68282 ist eine nutzlose Frage, warum Sie sich explizit als erstes Argument für Methoden setzen müssen; Diese Frage fragt nach dem Unterschied zwischen Klassen- und Instanzmitgliedern. S.Lott, ich mag deine Beiträge zu SO sehr, aber diesmal liegst du falsch.

Antworten:

137

A.xist eine Klassenvariable . B's self.xist eine Instanzvariable .

dh A's xwird zwischen Instanzen geteilt.

Es wäre einfacher, den Unterschied mit etwas zu demonstrieren, das wie eine Liste geändert werden kann:

#!/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)

Ausgabe

A's x: [1, 1]
B's x: [1]
Douglas Leeder
quelle
8
Vielleicht auch die Ausgabe Ihres Skripts posten, dann kann man den Unterschied sehen, ohne es selbst zu kopieren und auszuführen ...
Martin
7
Ich habe die Ausgabe hinzugefügt.
UnkwnTech
2
Entspricht Pythons Selbst dem von Java? Entschuldigen Sie bitte die Noobishness
Jean Azzopardi
2
@Jean - Yes-ish - self muss nur der herkömmliche Name sein, der dem ersten Parameter von Instanzmethoden gegeben wird - und Python übergibt die aktuelle Instanz von Instanzmethoden explizit als erstes Argument an Instanzmethoden. Aber es macht den gleichen Job wie Java
Douglas Leeder
@ Jean Azzopardi: Selbst ist fast wie Java (und C ++) dies. Selbst ist einfach erforderlich; Dies wird manchmal vom Java-Compiler begründet (manchmal ist es erforderlich).
S.Lott
54

Nur als Randnotiz: selfIst eigentlich nur ein zufällig ausgewähltes Wort, das jeder verwendet, aber Sie können es auch verwenden this, foooder myselfoder irgendetwas anderes, das Sie wollen, es ist nur der erste Parameter jeder nicht statischen Methode für eine Klasse. Dies bedeutet, dass das Wort selfkein Sprachkonstrukt ist, sondern nur ein Name:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2
André
quelle
1
Warum ist dies eine Antwort und kein Kommentar
Gabriel Petersson
23

Ax ist eine Klassenvariable und wird für alle Instanzen von A gemeinsam genutzt, sofern dies nicht innerhalb einer Instanz ausdrücklich überschrieben wird. Bx ist eine Instanzvariable, und jede Instanz von B hat eine eigene Version davon.

Ich hoffe, das folgende Python-Beispiel kann dies verdeutlichen:


    >>> 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
quelle
16

Ich habe es mit diesem Beispiel erklärt

# 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

Die Ausgabe erfolgt dann durch

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

machine1.counter 3
machine2.counter 3
machine3.counter 3
TMOTTM
quelle
3

Ich habe gerade angefangen, Python zu lernen, und das hat mich auch einige Zeit verwirrt. Um herauszufinden, wie das alles im Allgemeinen funktioniert, habe ich mir diesen sehr einfachen Code ausgedacht:

# 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()

Wenn wir anrufen out(), bekommen wir:

>>> obj.out()

red!

Wenn wir anrufen out2():

>>> obj.out2()

blue!

Wenn wir anrufen out3():

>>> obj.out3()

green!

In der ersten Methode wird also selfangegeben, dass Python die Variable (Attribut) verwenden soll, die zu dem von uns erstellten Klassenobjekt "gehört", nicht zu einem globalen (außerhalb der Klasse). Also nutzt es color = "red". In der Methode ersetzt Python implizit selfden Namen eines von uns erstellten Objekts ( obj). self.colorbedeutet "Ich komme color="red"von der obj"

Bei der zweiten Methode muss selfdas Objekt, von dem die Farbe übernommen werden soll, nicht angegeben werden, sodass das globale Objekt erhalten wird color = 'blue'.

Bei der dritten Methode haben selfwir stattdessen obj2einen Namen eines anderen Objekts verwendet, von dem wir abrufen möchten color. Es wird color = 'green'.

Yabee-Dabee
quelle