String und Tuple unterscheiden, bzw. unterschiedlich auswert

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MrNiceTry
User
Beiträge: 80
Registriert: Samstag 7. November 2009, 10:32

Hallo.

Ich bekomme aus einer Exec-Funktion Parameter geliefert.
Dies kann entweder ein String sein (nur ein Wert) oder ein Tuple (wenn mehrere Werte übergeben werden).
Ich habe keinen Einfluß darauf, ob ein String oder ein Tuple bei mir ankommt.
Nun sollen die erhaltenen Werte an eine Liste angehängt werden.
Bei String ist mir klar wie.
Aber was mache ich wenn ein Tuple kommt ?

if TUPLE .... ?
Oder gibt es was Integriertes ?

Danke für's Mitdenken.


MrNiceTry
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

MrNiceTry hat geschrieben:Nun sollen die erhaltenen Werte an eine Liste angehängt werden.
Bei String ist mir klar wie.
Aber was mache ich wenn ein Tuple kommt ?

Code: Alles auswählen

foo = [1]
bar = (2, 4, 8)
foo.extend(bar)
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Ein Tuple kann man so erkennen:

Code: Alles auswählen

>>> a = (1, 2, 3)
>>> type(a) == type(())
True
>>> 
Aber schön ist das nicht, weil du so keine Listen erkennst die du genauso verarbeiten könntest.
Andersrum hat man das Problem bei unicode/string.

Daher würde mich auch mal interessieren wie man das sauber unterscheiden kann.

Gruß
sparrow
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

wenn man sowas überhaupt explizit überprüfen möchte, würde man mMn eher isinstance() nutzen:

Code: Alles auswählen

>>> isinstance([123,456], (list, tuple))
True
Das geht dann auch für Tuple.

Besten Gruß,

brb
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Barabbas hat geschrieben:wenn man sowas überhaupt explizit überprüfen möchte, würde man mMn eher isinstance() nutzen:

Code: Alles auswählen

>>> isinstance([123,456], (list, tuple))
True
Supi, das ist eine tolle Lösung.

Wie wäre es denn für den Threadersteller ohne explizite Prüfung möglich sein Vorhaben umzusetzen?
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo,

die Frage habe ich mir auch gestellt. Wenn dir die Schnittstelle sowohl Strings als auch Tuples liefert, scheint nicht viel anderes übrig zu bleiben, als zu überprüfen, ob die jeweiligen Daten jetzt Strings oder Tuples sind.
Meine vorsichtige Formulierung bezog sich in diesem Fall also weniger darauf, dass ich eine bessere Lösung parat hätte, als darauf, dass ich betonen wollte, dass man nach Möglichkeit versucht, sowas zu vermeiden (Stichwort "Duck Typing"). Da Strings und Tuple aber letztlich jeweils Iterables sind, scheint mir dieser Ansatz in diesem Fall nicht sonderlich fruchtbar. Aber ich lasse mich da gerne belehren, ich mache mir ja auch nur meine Gedanken :).

Besten Gruß,

brb

//edit: Nur um zu klären, wie ich das mit den Iterables meinte: Wenn man beispielsweise nicht zwischen Strings und Tuples, sondern zwischen Ints und Tuples unterscheiden müsste, könnte man statt eines expliziten Typ-Vergleichs folgendes machen:

Code: Alles auswählen

value = 3 #oder wahlweise ein Tuple wie (3, 5, )
data = []
try:
    data.extend(value)
except TypeError:
    data.append(value)
Das wäre in so weit eine generischere Vorgehensweise, als dass alle Objekte, die __getitem__ oder __iter__ implementieren korrekt mit extend() in die Liste aufgenommen würden. Die Objekte, die diese Methoden nicht implementieren, würden aber zunächst einen TypeError werfen und dann ganz normal mit append() in die Liste aufgenommen werden.

Aber wie gesagt: Für den TE kommt diese Vorgehensweise so nicht in Frage, weil eben sowohl Strings als auch Tuples Iterables sind und somit über extend() aufgenommen werden. Die Strings dann aber Zeichen für Zeichen - was ja in diesem Fall nicht erwünscht sein dürfte.
Zuletzt geändert von Barabbas am Donnerstag 17. Februar 2011, 12:07, insgesamt 1-mal geändert.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Ich könnte mir sowas vorstellen:

Code: Alles auswählen

output_list = []
output = #str or list

func = output_list.append if type(output) is str else output_list.extend
func(output)
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was haben denn alle gegen isinstance? (bis auf Barabbas ;-) )

Code: Alles auswählen

func = output_list.append if isinstance(output, str) else output_list.extend
func(output)
Wobei man sinnvoller Weise wohl eher auf "tuple" testen würde; eine Funktion liefert ja irgend ein Objekt, oder ein Tupel von Objekten.
Zuletzt geändert von Hyperion am Donnerstag 17. Februar 2011, 12:15, insgesamt 1-mal geändert.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Ich würde auch sagen, dass die API an der Stelle einfach unschön ist. Um das "duck typing" möglichst wenig zu beeinträchtigen würde ich übrigens auf die Zeichenkette prüfen und nicht auf das Tupel. In der Praxis "erfinden" die Leute nämlich eher eigene, iterierbare Containertypen statt Zeichenketten abzuleiten. Ungetestet:

Code: Alles auswählen

    if isinstance(param, basestring):
        data.append(param)
    else:
        data.extend(param)
@mutetella: Wenn schon dann gleich komplett in einer Zeile und ohne Namen zu wiederholen:

Code: Alles auswählen

    getattr(data, 'append' if isinstance(param, basestring) else 'extend')(param)
:-)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Das ist cool, auf sowas steh' ich... :D
Danke!

Und isinstance() ist natürlich auch schöner als type(). Wenn man über Typprüfung nachdenkt, dann drängt sich halt dieses 'type' auf... :wink:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:Ich würde auch sagen, dass die API an der Stelle einfach unschön ist. Um das "duck typing" möglichst wenig zu beeinträchtigen würde ich übrigens auf die Zeichenkette prüfen und nicht auf das Tupel. In der Praxis "erfinden" die Leute nämlich eher eigene, iterierbare Containertypen statt Zeichenketten abzuleiten.
Das ist meiner Meinung nach tatsächlich der einzig sinnvolle Weg.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Hat man etwas, das entweder ein () oder ein [] ist, und man will testen, was was ist, ohne isinstance zu benutzen (was der naheliegende Weg wäre) fällt mir folgendes ein:

Code: Alles auswählen

def is_tuple(x):
    try:
        () + x
        return True
    except TypeError:
        return False

def is_list(x):
    try:
        [] + x
        return True
    except TypeError:
        return False
Stefan
Antworten