Seite 1 von 1
[] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 10:33
von serendip82
Hi,
ich versuche gerade mein Listenobjekt zu überladen... oder zu modifizieren. Dabei haben ich festgestellt, dass
Code: Alles auswählen
class list(list):
def __init__(self,value=[]):
self.value=value
print value
def __get_id__(self):
out=[]
for i in self.value:
out.append(i.id)
return out
id = property(__get_id__)
keinen Einfluss auf listen hat, die mit [] initialisiert wurden. Folgendes funktioniert natürlich nicht:
Code: Alles auswählen
class []([]):
def __init__(self):
print "Hallo"
File "<ipython-input-11-e5b4f05dd611>", line 1
class []([]):
SyntaxError: invalid syntax
Was ist denn der Unterschied zwischen [] und list()? Kann man [] auch modifizieren?
PS: Ist überladen hier der richtige Begriff oder gibt es prägnanteren Begriff für das was ich versuche?
Was ich eigentlich erreichen möchte ist, dass wenn meine liste [a,b] kein attribut X hat, es eine Liste zurückgibt mit den atributen X der Elemente: [a.X,b.X]
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 10:44
von /me
serendip82 hat geschrieben:Was ist denn der Unterschied zwischen [] und list()? Kann man [] auch modifizieren?
Nein. Du kannst nicht mal die Klasse
list wirklich modifizieren.
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 10:47
von lunar
serendip82 hat geschrieben:Kann man [] auch modifizieren?
Glücklicherweise nicht.
serendip82 hat geschrieben:Was ich eigentlich erreichen möchte ist, dass wenn meine liste [a,b] kein attribut X hat, es eine Liste zurückgibt mit den atributen X der Elemente: [a.X,b.X]
Warum solche Magie? Ist Dir ein einfaches "map(attrgetter('X'), [a, b])" zu uncool?
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 10:59
von Sirius3
@serendip82: mit Deinem "class list..." erzeugst Du eine neue Klasse die in Deinem Namensraum an den Namen "list" gebunden wird.
Der eingebaute list-Klasse auf die [] direkt zurückgreift ist das ziemlich egal. Willst Du wirklich eine Klasse erzeugen, die "list" überlädt, lies Dir den entsprechenden Abschnitt in der Python-Dokumentation durch. Dann kannst Du zwar nicht [] dafür benutzen aber "SpecialList(...)" ist ja auch nicht komplizierter zu schreiben.
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 11:21
von serendip82
Danke für die Antworten. Ich gehe den Hinweisen gleich nach.
Hier ist schonmal etwas, das so funktioniert, wie ich es haben möchte:
Code: Alles auswählen
class l(list):
def __init__(self):
self.values=self
def __getattr__(self, attr):
output=self.values
try:
for i in range(len(self.values)):
output[i]=getattr(output[i],attr)
return output
except:
raise AttributeError
@ Sirius3: Das ist mir klar, wenn ich ein neue classe list() generiere, werden alle neuen Instanzen mit der modifizierten version generiert. Ich habe in meinem Skript viele listen mit [] generiert und ich wollte diesen listen mit einer neuen Funktion ausstatten.
ließ Dir den entsprechenden Abschnitt in der Python-Dokumentation
Welches ist denn der entsprechende Abschnitt? Bei "overloading" finde ich nichts offensichtlich sinnvolles...
@ luna: warum "glücklicherweise" ? map(attrgetter('X'), [a, b]) kenne ich noch nicht... aber danke für den Tipp.
@ /me thanks
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 11:27
von lunar
@serendip82 Nun, das Überladen von Literalen ist der Lesbarkeit und Verständlichkeit, sagen wir, nicht gerade zuträglich… dürfte man das in Python, dann würde jeder so “clevere” Tricks in seinen Quelltext einbauen, und man wüsste ob der dynamischen Natur der Sprache nie, mit welchem Typ man es zu tun hat. Würde man dann zwei Bibliotheken verwenden, die jeweils unterschiedliche Auffassungen von "[]" haben, das gäbe einen Spaß…
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 11:37
von BlackJack
@serendip82: Deine `l`-Klasse macht keinen Sinn. Du benutzt den Umstand das es eine Unterklasse von `list` ist überhaupt gar nicht. Du hast da einmal die Werte in der Liste und dann nochmal Werte im `values`-Attribut.
Glücklicherweise kann man nicht alle Listen im ganzen Programm auf diese Weise ändern, weil Du damit ja das Verhalten von *allen* Listen änderst, auch für Code der gar nicht von Dir ist, sondern in Modulen die Du verwendest, der mit Deiner veränderten Liste am Ende gar nicht klar kommt und auf mysteriöse Weise auf die Nase fällt. Wenn das ginge würdest nicht nur Du auf die Idee kommen. Was ist dann wenn ein anderes Modul welches Du benutzt auch `__getattr__()` für etwas anderes verwenden möchte?
Die API ist auch nicht wirklich schön. Was ist wenn man ein Attribut von den Elementen haben möchte was es *auch* auf Listen gibt? Mir wäre das zu magisch. Du kannst offensichtlich nicht mal grundlegend mit Klassen umgehen, implementierst aber schon so eine undurchsichtige Magie mit dynamischen Attributzugriffen. Ich würde das entweder ganz weglassen, denn ``[o.x for x in some_iterable]`` macht klar wo die Liste herkommt. Oder man erstellt einen Listen-Typ mit einer Methode: ``special_list.get_attributes('x')``. Da kann man dann als Argument alles angeben ohne Gefahr zu laufen eine Namenskollision mit Attributen des `special_list`-Objekts zu haben.
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 11:52
von serendip82
@ BlackJack
Klar, ist alles etwas "gebastelt". Ich probiere eben gerade aus, was alles geht, und wie es geht... Dass ich den Umstand, dass es eine Unterklasse von "list" ist nicht benutze, liegt daran, dass ich nicht weiß wie es richtig geht und mir entsprechende Suchen nicht zu dem gewünschten Wissen verholfen haben. Wie kann man denn einem Objekt das iterierbar ist sagen, dass es auf seine Elemente zugreifen soll? Oder noch besser, wo kann ich es nachlesen, wie es richtig geht? Die Dokumentation ist mir da zu kryptisch und zu technisch.
OkOk, dass ich nicht listen generell veränder sollte akzeptiere ich. Trotzdem würde ich mir gerne eine special_List bauen, die das tut, was ich möchte...
Leider funktioniert die l() klasse auch nicht so richtig.
l(['a','b']) versteht die klasse nicht...
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 12:01
von jerch
Ungetestet:
Code: Alles auswählen
from operator import attrgetter
class MyList(list):
def __getitem__(self, num):
try:
return list.__getitem__(self, num)
except IndexError:
# hier kommt Deine Anpassung rein z.B.
return map(attrgetter('X'), [a, b])
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 12:09
von BlackJack
@serendip82: Wenn man Methoden einer Klasse überschreibt sollte man überlegen ob man die Methode der Superklasse einfach so ersatzlos streicht oder ob man die nicht vielleicht selber aufrufen möchte. Insbesondere in der `__init__()` fehlt sonst ja der Initialisierungsteil der Basisklasse. Andererseits: Wenn man selber eigentlich nichts sinnvolles zu tun hat, warum dann überhaupt eine eigene `__init__()` implementieren‽
Auf die Elemente eines iterierbaren Objekts greift man zu in dem man darüber iteriert. Klingt vielleicht ein bisschen offensichtlich — ist es auch. Das kann man mit ``for`` machen, oder mit einer „list comprehension” (LC) oder einer Funktion die über die Elemente iteriert.
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 12:14
von serendip82
Code: Alles auswählen
from operator import attrgetter
class MyList(list):
def __getitem__(self, num):
try:
return list.__getitem__(self, num)
except IndexError:
# also ungefähr so
return map(attrgetter(num), self)
a=MyList(M.a)
print [i.x for i in M.a]
->[array([2, 0, 0]), array([2, 1, 0]), array([3, 0, 0]), array([1, 0, 0]), array([4, 0, 0])]
print a.x
->AttributeError: 'MyList' object has no attribute 'x'
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 12:30
von jerch
@serendip82:
Irgendwie hab ich Index statt Attribut gelesen
Hier mit Attribut:
Code: Alles auswählen
from operator import attrgetter
class MyList(list):
def __getattribute__(self, name):
try:
return list.__getattribute__(self, name)
except AttributeError:
return map(attrgetter(name), self)
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 12:31
von BlackJack
@serendip82: Da Du `__getattr__` nicht überschreibst und Listen kein `x`-Attribut haben ist das zu erwarten gewesen.
Re: [] != list() ? Add new functions to list()....
Verfasst: Mittwoch 2. Oktober 2013, 22:16
von Leonidas
BlackJack hat geschrieben:@serendip82: Da Du `__getattr__` nicht überschreibst und Listen kein `x`-Attribut haben ist das zu erwarten gewesen.
Ist ja auch der Code von jerch oben drüber
