Nach dem, was Sie geschrieben haben, fehlt Ihnen ein kritisches Stück Verständnis: der Unterschied zwischen einer Klasse und einem Objekt. __init__initialisiert keine Klasse, sondern eine Instanz einer Klasse oder eines Objekts. Jeder Hund hat Farbe, Hunde als Klasse jedoch nicht. Jeder Hund hat vier oder weniger Füße, die Klasse der Hunde jedoch nicht. Die Klasse ist ein Konzept eines Objekts. Wenn Sie Fido und Spot sehen, erkennen Sie ihre Ähnlichkeit, ihre Doghood. Das ist die Klasse.
Wenn du sagst
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
Du sagst, Fido ist ein brauner Hund mit 4 Beinen, während Spot ein bisschen verkrüppelt und meistens gelb ist. Die __init__Funktion wird als Konstruktor oder Initialisierer bezeichnet und automatisch aufgerufen, wenn Sie eine neue Instanz einer Klasse erstellen. Innerhalb dieser Funktion wird das neu erstellte Objekt dem Parameter zugewiesen self. Die Notation self.legsist ein Attribut, das legsvom Objekt in der Variablen aufgerufen wird self. Attribute ähneln Variablen, beschreiben jedoch den Status eines Objekts oder bestimmte Aktionen (Funktionen), die dem Objekt zur Verfügung stehen.
colourBeachten Sie jedoch, dass Sie sich nicht auf die Doghood selbst einstellen - es ist ein abstraktes Konzept. Es gibt Attribute, die für Klassen sinnvoll sind. Ist zum Beispiel population_sizeeine solche - es macht keinen Sinn, den Fido zu zählen, weil Fido immer einer ist. Es ist sinnvoll, Hunde zu zählen. Nehmen wir an, es gibt 200 Millionen Hunde auf der Welt. Es ist Eigentum der Hundeklasse. Fido hat nichts mit der Zahl von 200 Millionen zu tun, Spot auch nicht. Es wird als "Klassenattribut" bezeichnet, im Gegensatz zu "Instanzattributen", die colouroder legshöher sind.
Nun zu etwas weniger Eckzahnigem und mehr Programmierbezogenem. Wie ich weiter unten schreibe, ist eine Klasse zum Hinzufügen von Dingen nicht sinnvoll - wovon ist eine Klasse? Klassen in Python bestehen aus Sammlungen verschiedener Daten, die sich ähnlich verhalten. Die Klasse der Hunde besteht aus Fido und Spot und 199999999998 ähnlichen Tieren, die alle auf Laternenpfählen pinkeln. Woraus besteht die Klasse zum Hinzufügen von Dingen? Durch welche ihnen innewohnenden Daten unterscheiden sie sich? Und welche Aktionen teilen sie?
Zahlen ... das sind jedoch interessantere Themen. Sagen wir, Ganzzahlen. Es gibt viele von ihnen, viel mehr als Hunde. Ich weiß, dass Python bereits Ganzzahlen hat, aber lasst uns dumm spielen und sie erneut "implementieren" (indem wir betrügen und Pythons Ganzzahlen verwenden).
Ganzzahlen sind also eine Klasse. Sie haben einige Daten (Wert) und einige Verhaltensweisen ("füge mich zu dieser anderen Zahl hinzu"). Lassen Sie uns dies zeigen:
class MyInteger:
def __init__(self, newvalue)
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
def add(self, other):
# when an integer wants to add itself to another integer,
# we'll take their values and add them together,
# then make a new integer with the result value.
return MyInteger(self.value + other.value)
three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8
Dies ist etwas fragil (wir gehen davon aus, dass otheres sich um eine MyInteger handelt), aber wir werden sie jetzt ignorieren. In echtem Code würden wir nicht; Wir würden es testen, um sicherzugehen und es vielleicht sogar zu erzwingen ("Sie sind keine ganze Zahl? Sie haben 10 Nanosekunden Zeit, um eins zu werden! 9 ... 8 ...")
Wir könnten sogar Brüche definieren. Brüche wissen auch, wie sie sich selbst hinzufügen können.
class MyFraction:
def __init__(self, newnumerator, newdenominator)
self.numerator = newnumerator
self.denominator = newdenominator
# because every fraction is described by these two things
def add(self, other):
newdenominator = self.denominator * other.denominator
newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
return MyFraction(newnumerator, newdenominator)
Es gibt sogar mehr Brüche als ganze Zahlen (nicht wirklich, aber Computer wissen das nicht). Machen wir zwei:
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
Sie erklären hier eigentlich nichts. Attribute sind wie eine neue Art von Variablen. Normale Variablen haben nur einen Wert. Sagen wir, Sie schreiben colour = "grey". Sie können nicht eine andere Variable mit dem Namen haben , colourdas ist "fuchsia"- nicht an der gleichen Stelle im Code.
Arrays lösen das bis zu einem gewissen Grad. Wenn Sie sagen colour = ["grey", "fuchsia"], Sie haben zwei Farben in die Variable gestapelt, aber Sie unterscheiden sie durch ihre Position (in diesem Fall 0 oder 1).
Attribute sind Variablen, die an ein Objekt gebunden sind. Wie bei Arrays können wir bei verschiedenen Hunden viele colourVariablen haben . Ist also eine Variable, aber eine andere. Der erste ist an das Objekt innerhalb der Variablen gebunden ; der zweite , . Wenn Sie jetzt oder aufrufen , wird immer ein unsichtbarer Parameter angezeigt, der dem baumelnden zusätzlichen Parameter am Anfang der Parameterliste zugewiesen wird. Es wird herkömmlicherweise aufgerufen und erhält den Wert des Objekts vor dem Punkt. So wird innerhalb des Hundes (Konstrukteurs) sein, was auch immer der neue Hund sein wird; innerhalb ‚s , wird auf das Objekt in den Variablen gebunden werden . So,fido.colourspot.colourfidospotDog(4, "brown")three.add(five)self__init__selfMyIntegeraddselfthreethree.valuewird die gleiche Variable außerhalb der add, wie self.valueinnerhalb der add.
Wenn ich sage the_mangy_one = fido, beziehe ich mich auf das Objekt fidomit einem anderen Namen. Von nun an fido.colourist genau die gleiche Variable wie the_mangy_one.colour.
Also, die Dinge in der __init__. Sie können sich vorstellen, dass sie Dinge in der Geburtsurkunde des Hundes vermerken. colouran sich ist eine zufällige Variable, könnte alles enthalten. fido.colouroder self.colourist wie ein Formularfeld auf dem Ausweis des Hundes; und __init__füllt der Angestellte es zum ersten Mal aus.
Noch klarer?
BEARBEITEN : Erweitern Sie den Kommentar unten:
Du meinst eine Liste von Objekten , nicht wahr?
Erstens fidoist eigentlich kein Objekt. Es ist eine Variable, die derzeit ein Objekt enthält, genau wie wenn Sie sagen x = 5, xeine Variable, die derzeit die Nummer fünf enthält. Wenn Sie später Ihre Meinung ändern, können Sie dies tun fido = Cat(4, "pleasing")(solange Sie eine Klasse erstellt haben Cat) und fidowürden fortan ein Katzenobjekt "enthalten". Wenn Sie dies tun fido = x, enthält es die Nummer fünf und überhaupt kein Tierobjekt.
Eine Klasse selbst kennt ihre Instanzen nur, wenn Sie speziell Code schreiben, um sie zu verfolgen. Zum Beispiel:
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
Hier censusist ein Attribut der CatKlasse auf Klassenebene.
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
Beachten Sie, dass Sie nicht bekommen [fluffy, sparky]. Das sind nur Variablennamen. Wenn Sie möchten, dass Katzen selbst Namen haben, müssen Sie ein separates Attribut für den Namen erstellen und dann die __str__Methode überschreiben , um diesen Namen zurückzugeben. Der Zweck dieser Methode (dh klassengebundene Funktion, genau wie addoder __init__) besteht darin, zu beschreiben, wie das Objekt in eine Zeichenfolge konvertiert wird, beispielsweise beim Ausdrucken.