Hallo zusammen,
ich sitze grade an einer Aufgabe, in der ich eine Klasse 'NumericVector' erstellen soll. Diese bekommt als Parameter *args. Ich bekomme es leider nicht hin, so viele Attribute, wie Einträge in *args zu erstellen. Die Idee ist, dass ich beim Aufruf der Attribute folgende Werte bekomme:
z.B. :
vec1 = NumericVector(1,2,3,4,5)
print(vec1.x1) -> Ausgabe: 1
print(vec1.x2) -> Ausgabe: 2
print(vec1.x3) -> Ausgabe: 3
print(vec1.x4) -> Ausgabe: 4
print(vec1.x5) -> Ausgabe: 5
Bisher sieht mein Code so aus:
class NumericVector():
def __init__(self, *vector):
for i, xi in enumerate(vector):
j = str(i+1)
self.j = xi
Allerdings überschriebt er hierbei immer wieder das Attribut self. j , also ich kann keinen Wert bzw. einen String zuweisen, dass für jeden Schleifendurchlauf unterscheidbare Attribute entstehen.
Über Ideen und Hilfen würde ich mich echt freuen!
Klasse mit variablen Parametern erstellen
Nein, man erzeugt nicht dynamisch Attribute, genausowenig wie man dynamisch Variablen erzeugt. Warum möchtest Du denn per vector.x3 auf Werte zugreifen? Der übliche Weg wäre vector[2].
Dazu definiert man die Methode __getitem__:
Dazu definiert man die Methode __getitem__:
Code: Alles auswählen
class Vector:
def __init__(self, *values):
self.values = values
def __getitem__(self, index):
return self.values[index]
vector = Vector(1,2,3,4,5)
print(vector[2])
- __blackjack__
- User
- Beiträge: 13118
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Wobei ich mit so magischen Signaturen vorsichtig wäre. Man nimmt sich da gerne mal die Möglichkeit die API zu ändern, und nicht selten braucht man dann in vielen Aufrufen auch wieder die Sternchenmagie, nur weil man das bei der Signatur so gemacht hat, und eigentlich an beiden Stellen auch prima ohne auskommen würde.
Code: Alles auswählen
class Vector:
def __init__(self, values):
self.values = values
def __getitem__(self, index):
return self.values[index]
vector = Vector([1, 2, 3, 4, 5])
print(vector[2])
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- DeaD_EyE
- User
- Beiträge: 1021
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Den Code würde ich nie verwenden
Das ist einfach schlecht, wenn "Attribute" aus dem Nichts kommen.
Das ist schlecht für die Autovervollständigung in der Entwicklungsumgebung.
Angenommen du würdest die Klasse z.B. in Pycharm oder VSCode vor dir haben und erstellst daraus eine Instanz. Wenn du dann von der Instanz den Namen eingibst mit einem folgenden Punkt, wird einem automatisch die Kandidaten (Attribute und Methoden) vorgeschlagen. Die Attribute x1 - x6 gibt es nicht und deswegen werden sie nicht angezeigt. Die dir() Funktion ruft die __dir__ Methode eines Objektes auf. Dann funktioniert das in der REPL, aber die IDE weiß dann immer noch nichts von x1 bis x6.
Der Index-Zugriff ist viel besser.
Code: Alles auswählen
class NumericVector:
def __init__(self, *vector):
self.vector = vector
def __dir__(self):
entries = super.__dir__(self)
entries.extend(f"x{i+1}" for i, _ in enumerate(self.vector))
return entries
def __getattr__(self, key):
if key.startswith("x") and key[1:].isdigit():
return self.vector[int(key[1:]) - 1]
Das ist schlecht für die Autovervollständigung in der Entwicklungsumgebung.
Angenommen du würdest die Klasse z.B. in Pycharm oder VSCode vor dir haben und erstellst daraus eine Instanz. Wenn du dann von der Instanz den Namen eingibst mit einem folgenden Punkt, wird einem automatisch die Kandidaten (Attribute und Methoden) vorgeschlagen. Die Attribute x1 - x6 gibt es nicht und deswegen werden sie nicht angezeigt. Die dir() Funktion ruft die __dir__ Methode eines Objektes auf. Dann funktioniert das in der REPL, aber die IDE weiß dann immer noch nichts von x1 bis x6.
Der Index-Zugriff ist viel besser.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
- __blackjack__
- User
- Beiträge: 13118
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
In `__getattr__` fehlt noch der Fall, dass die ``if``-Bedingung nicht zutrifft, denn sonst hat dieses Objekt ja quasi *alle* Attribute die man da abfragen könnte und liefert für alle ausser den x<nummer> Attributen den Wert `None`.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- DeaD_EyE
- User
- Beiträge: 1021
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Stimmt
Ich wusste schon, wieso ich mir gar keine Mühe gegeben habe.
Wenn man noch länger sucht, wird man noch anderes finden, dass sich von normalen Klassen unterscheidet. x1 - x... ist z.B. auch nicht im __dict__ der Klasse vorhanden.
Ich wusste schon, wieso ich mir gar keine Mühe gegeben habe.
Wenn man noch länger sucht, wird man noch anderes finden, dass sich von normalen Klassen unterscheidet. x1 - x... ist z.B. auch nicht im __dict__ der Klasse vorhanden.
Code: Alles auswählen
class NumericVector:
def __init__(self, *vector):
self.vector = vector
def __dir__(self):
entries = super.__dir__(self)
entries.extend(f"x{i+1}" for i, _ in enumerate(self.vector))
return entries
def __getattr__(self, key):
if key.startswith("x") and key[1:].isdigit():
return self.vector[int(key[1:]) - 1]
raise AttributeError(f"'{self}' has no attribute '{key}'")
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Danke euch allen! Ich lerne gerade die Grundlagen von Python und ich kenne noch nicht so viele Wege bestimmte Codes zu realisieren. Da wir in der Vorlesung gelernt haben so auf Attribute zuzugreifen (variable.attribut), wollte ich es auf diese Weise lösen. Ich werde versuchen den Code mit euren Vorschlägen zu realisieren und hoffe, dass es klappt, da unsere Abgaben mit automatischen Tests überprüft werden und es in der Regel nur einen richtigen Lösungsweg gibt.
Danke
Danke
Ich vermute, die Lösung der Aufgabenstellung soll so aussehen:
Das ist aber keine gute Idee, da Instanzen von NumericVector nun zur Laufzeit unterschiedliche Attribute haben können und zudem im Code nicht ersichtlich ist, wie diese lauten. Das ist sehr fragil und gibt früher oder später Ärger.
Code: Alles auswählen
class NumericVector:
def __init__(self, *args):
for index, item in enumerate(args, start=1):
setattr(self, f"x{index}", item)
Das ist aber keine gute Idee, da Instanzen von NumericVector nun zur Laufzeit unterschiedliche Attribute haben können und zudem im Code nicht ersichtlich ist, wie diese lauten. Das ist sehr fragil und gibt früher oder später Ärger.