Das ist meine Klasse:
""" Class definition for a citrus plant. """
import random
class Citrus:
def __init__(self, species: str = None, possible_species = ("Pomelo", "Mandarin", "Citron")):
if species == None:
self.species = random.choice(possible_species)
else:
self.species = species
def __str__(self):
return "<Citrus of species " + self.species + ">"
def __add__(self, other):
if not isinstance(type(self), type(Citrus) ) or not isinstance(type(other), type(Citrus)):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
elif self.species == other.species:
return Citrus(self.species)
elif (self.species == "Pomelo" and other.species == "Mandarin") or (self.species == "Mandarin" and other.species == "Pomelo"):
return random.choice([Citrus("Sweet Orange"), Citrus("Tangerine"), Citrus("Satsuma"), Citrus("Wildleaf Mandarin"), Citrus("Bitter Orange")])
elif (self.species == "Pomelo" and other.species == "Sweet Orange") or (self.species == "Sweet Orange" and other.species == "Pomelo"):
return Citrus("Grapefruit")
elif (self.species == "Wildleaf Mandarin" and other.species == "Sweet Orange") or (self.species == "Sweet Orange" and other.species == "Wildleaf Mandarin"):
return Citrus("Clementine")
elif (self.species == "Citron" and other.species == "Bitter Orange") or (self.species == "Bitter Orange" and other.species == "Citron"):
return Citrus("Lemon")
else:
return random.choice([Citrus(self.species), Citrus(other.species)])
def __radd__(self):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
Fehlermeldung:
File "/home/.../citrus.py", line 20, in __add__
elif self.species == other.species:
AttributeError: type object 'Citrus' has no attribute 'species'
Die kommt beim verwenden der Add-Methode, was mach ich falsch?
LG
Meine eigene Klasse kennt sich selbst nicht
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@kopython: Du übergibst da offenbar etwas falsches. Wäre ja nett gewesen zu sehen *was*.
Die erste ``if``-Bedingung in `__add__()` ist falsch. Die `type()`-Aufrufe haben da so überhaupt nichts zu suchen.
Und wenn man das korrigiert ist die erste Teilbedingung unsinnig, denn `self` ist *immer* ein `Citrus`-Exemplar, denn das ist ja `Citrus.__add__()`.
Die Regeln die danach folgen würde ich als Datenstruktur formulieren statt mit so viel Code. Und vielleicht nicht so verdammt viele `Citrus`-Objekte erstellen die gleich darauf wieder verworfen werden.
Die erste ``if``-Bedingung in `__add__()` ist falsch. Die `type()`-Aufrufe haben da so überhaupt nichts zu suchen.
Und wenn man das korrigiert ist die erste Teilbedingung unsinnig, denn `self` ist *immer* ein `Citrus`-Exemplar, denn das ist ja `Citrus.__add__()`.
Die Regeln die danach folgen würde ich als Datenstruktur formulieren statt mit so viel Code. Und vielleicht nicht so verdammt viele `Citrus`-Objekte erstellen die gleich darauf wieder verworfen werden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ich habe das mal etwas verändert und bei mir läuft es so:
Code: Alles auswählen
import random
variants = {("Pomelo", "Mandarin") : ("Sweet Orange", "Tangerine", "Satsuma", "Wildleaf Mandarin", "Bitter Orange"),
("Mandarin", "Pomelo") : ("Sweet Orange", "Tangerine", "Satsuma", "Wildleaf Mandarin", "Bitter Orange"),
("Pomelo", "Sweet Orange") : ("Grapefruit", ),
("Sweet Orange", "Pomelo") : ("Grapefruit", ),
("Wildleaf Mandarin", "Sweet Orange") : ("Clementine", ),
("Sweet Orange", "Wildleaf Mandarin") : ("Clementine", ),
("Citron", "Bitter Orange") : ("Lemon", ),
("Bitter Orange", "Citron") : ("Lemon", ),
}
class Citrus:
def __init__(self, species = None, possible_species = ("Pomelo", "Mandarin", "Citron")):
self.species = species or random.choice(possible_species)
def __str__(self):
return "<Citrus of species " + self.species + ">"
def __repr__(self):
return "<Citrus of species " + self.species + ">"
def __add__(self, other):
if not isinstance(other, Citrus):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
if self.species == other.species:
return Citrus(self.species)
try:
return Citrus(random.choice(variants[(self.species, other.species)]))
except KeyError:
return Citrus(random.choice([self.species, other.species]))
def __radd__(self):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Wieder so ein Fall, wo die Typannotation offensichtlich falsch ist, da der Defaultwert von `species` kein String ist.
`possible_species` wäre wohl besser eine Klassenkonstante.
Auf None testet man mit ›is‹.
Statt Strings mit + zusammenzustückeln benutzt man Format-Strings.
Bei __radd__ fehlt das zweite Argument. Aber wenn es eh nicht implementiert ist, kann man das ja auch weglassen.
Und ohne den Code, der die Klasse aufruft, kann man nichts zum Fehler sagen.
`possible_species` wäre wohl besser eine Klassenkonstante.
Auf None testet man mit ›is‹.
Statt Strings mit + zusammenzustückeln benutzt man Format-Strings.
Bei __radd__ fehlt das zweite Argument. Aber wenn es eh nicht implementiert ist, kann man das ja auch weglassen.
Code: Alles auswählen
import random
class Citrus:
POSSIBLE_SPECIES = ["Pomelo", "Mandarin", "Citron"]
def __init__(self, species=None):
if species is None:
species = random.choice(self.POSSIBLE_SPECIES)
self.species = species
def __str__(self):
return f"<Citrus of species {self.species}>"
def __add__(self, other):
if not isinstance(other, Citrus):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
elif self.species == other.species:
return Citrus(self.species)
elif set(self.species, other.species) == {"Pomelo", "Mandarin"}:
return Citrus(random.choice(["Sweet Orange", "Tangerine", "Satsuma", "Wildleaf Mandarin", "Bitter Orange"]))
elif set(self.species, other.species) == {"Pomelo", "Sweet Orange"}:
return Citrus("Grapefruit")
elif set(self.species, other.species) == {"Wildleaf Mandarin", "Sweet Orange"}:
return Citrus("Clementine")
elif set(self.species, other.species) == {"Citron", "Bitter Orange"}:
return Citrus("Lemon")
else:
return Citrus(random.choice([self.species, other.species]))
Vielen Dank schonmal! Ich habe den etwas schickeren Code übernommen aber hänge damit jetzt an der nächsten Stelle fest.
Der gesamte Code:
Mit folgender Fehlermeldung:
Traceback (most recent call last):
File ".../simulate.py", line 59, in <module>
main()
File ".../simulate.py", line 13, in main
simulate_garden()
File ".../simulate.py", line 51, in simulate_garden
my_garden.cross()
File ".../garden.py", line 29, in cross
crossed_citrus = random.choice(self.plants) + random.choice(self.plants)
TypeError: unsupported operand type(s) for +: 'type' and 'type'
Der gesamte Code:
Code: Alles auswählen
""" Class definition for a citrus plant. """
import random
variants = {("Pomelo", "Mandarin") : ("Sweet Orange", "Tangerine", "Satsuma", "Wildleaf Mandarin", "Bitter Orange"),
("Mandarin", "Pomelo") : ("Sweet Orange", "Tangerine", "Satsuma", "Wildleaf Mandarin", "Bitter Orange"),
("Pomelo", "Sweet Orange") : ("Grapefruit", ),
("Sweet Orange", "Pomelo") : ("Grapefruit", ),
("Wildleaf Mandarin", "Sweet Orange") : ("Clementine", ),
("Sweet Orange", "Wildleaf Mandarin") : ("Clementine", ),
("Citron", "Bitter Orange") : ("Lemon", ),
("Bitter Orange", "Citron") : ("Lemon", ),
}
class Citrus:
def __init__(self, species = None, possible_species = ("Pomelo", "Mandarin", "Citron")):
self.species = species or random.choice(possible_species)
def __str__(self):
return "<Citrus of species %s >"% (self.species)
def __repr__(self):
return "<Citrus of species %s >"% (self.species)
def __add__(self, other):
if not isinstance(other, Citrus):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
if self.species == other.species:
return Citrus(self.species)
try:
return Citrus(random.choice(variants[(self.species, other.species)]))
except KeyError:
return Citrus(random.choice([self.species, other.species]))
def __radd__(self):
raise TypeError("plant not excepted. Both plants should be of type Citrus")
Code: Alles auswählen
""" Class definition for a garden with plants. """
from citrus import Citrus
import random
class Garden:
def __init__(self, plants: list = []) -> None:
self.plants = plants
def __len__(self):
return len(self.plants)
def __str__(self):
return "<Garden with " + str(len(self.plants)) + " plants and " + str(len(set(self.plants))) + " species> "
def plant(self, new_plant = None):
if new_plant == None :
self.plants.append(Citrus)
else:
self.plants.append(new_plant)
def cross(self):
if len(self.plants) >= 2:
crossed_citrus = random.choice(self.plants) + random.choice(self.plants)
self.plant(crossed_citrus)
Code: Alles auswählen
""" Script to simulate a garden full of citrus plants. """
from garden import Garden
from citrus import Citrus
def main():
print("\n" + "#" * 20, "Simulating Citrus", "#" * 20)
simulate_citrus()
print("\n" + "#" * 20, "Simulating Garden", "#" * 20)
simulate_garden()
def simulate_citrus():
""" Simulates instances of class Citrus. """
print("\nCreating a Citrus my_citrus ...")
my_citrus = Citrus()
print("\nPrinting my_citrus...")
print(my_citrus)
print("\nCreating a Citrus other_citrus ...")
other_citrus = Citrus()
print("\nPrinting other_citrus ...")
print(other_citrus)
print("\nPrinting my_citrus + other_citrus ...")
print(my_citrus + other_citrus)
def simulate_garden():
""" Simulates an instance of class Garden. """
print("\nCreating a Garden my_garden ...")
my_garden = Garden()
print(my_garden)
print("\nPlanting 5 Citrus plants ...")
for _ in range(5):
my_garden.plant()
print(my_garden)
print("\nCrossing plants in my_garden 20 times ...")
for _ in range(20):
my_garden.cross()
print(my_garden)
print("\nThe following species now exist in the garden:", {plant.species for plant in my_garden.plants}, "\n")
if __name__ == "__main__":
main()
Traceback (most recent call last):
File ".../simulate.py", line 59, in <module>
main()
File ".../simulate.py", line 13, in main
simulate_garden()
File ".../simulate.py", line 51, in simulate_garden
my_garden.cross()
File ".../garden.py", line 29, in cross
crossed_citrus = random.choice(self.plants) + random.choice(self.plants)
TypeError: unsupported operand type(s) for +: 'type' and 'type'
Nun, scheinbar funktioniert
nicht.
Die Frage dabei ist, was ist denn in self.plants enthalten? Der Fehler (den ich gesehen habe) liegt in Garden.plant().
Code: Alles auswählen
crossed_citrus = random.choice(self.plants) + random.choice(self.plants)
Die Frage dabei ist, was ist denn in self.plants enthalten? Der Fehler (den ich gesehen habe) liegt in Garden.plant().
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
@kopython: man schreibt nicht pro Klasse ein eigenes Modul. Im jetzigen Zustand macht mehr als eine einzige Datei noch keinen Sinn.
In Garden.__init__ benutzt Du eine Liste als Defaultargument. Das ist ein schwer zu findender Fehler, denn es existiert nur eine einzige Liste für alle Garden-Instanzen. Man muß in __init__ für jede Instanz eine eigene Liste erzeugen.
Und wie ich schon geschrieben hatte, werden Strings nicht mit + zusammengestückelt, sondern man benutzt Format-Strings. Mit None wird per ›is None‹ verglichen.
Garden.plant fügt die Citrus-Klasse in self.plants ein, das ist falsch, Du willst ja eine Instanz hinzufügen.
In Garden.cross machst Du einfach nichts, wenn nicht genug Pflanzen gepflanzt worden sind; einfach nichts zu tun, ist aber oft nicht gut, weil damit Fehler schwer zu entdecken sind.
In Garden.__init__ benutzt Du eine Liste als Defaultargument. Das ist ein schwer zu findender Fehler, denn es existiert nur eine einzige Liste für alle Garden-Instanzen. Man muß in __init__ für jede Instanz eine eigene Liste erzeugen.
Und wie ich schon geschrieben hatte, werden Strings nicht mit + zusammengestückelt, sondern man benutzt Format-Strings. Mit None wird per ›is None‹ verglichen.
Garden.plant fügt die Citrus-Klasse in self.plants ein, das ist falsch, Du willst ja eine Instanz hinzufügen.
In Garden.cross machst Du einfach nichts, wenn nicht genug Pflanzen gepflanzt worden sind; einfach nichts zu tun, ist aber oft nicht gut, weil damit Fehler schwer zu entdecken sind.
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@kopython: Die `__str__()`-Implementierungen sollten weg bzw. `__repr__()`-Implementierungen sein. Die vom `Garden` hat einen Fehler weil auch `Citrus`-Objekte mit dem gleichen `species`-Wert zwei Elemente in einem `set` sind und nicht nur einer. ``str(len(self.plants))`` ist auch unnötig umständlich wenn `self` doch selbst schon als Argument für `len()` verwendet werden kann.
Die Vorsilben `my_` und `new_` machen nicht wirklich Sinn und können weg.
Die Vorsilben `my_` und `new_` machen nicht wirklich Sinn und können weg.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari