was ist in python eigentlich besser ?

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.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Bei folgende simplen Style-Fragen, würden mich mal eure Meinungen hören

try ... except ... wann nimmt man das statt if

zB.: was ist hier besser

Code: Alles auswählen

# dict_.has_key(...) fällt ja in 3.x weg
if key in dict_:
    print(dict_[key])

#oder 

try:
    print(dict_[key])
except KeyError:
    pass
dann wie setzt man am besten mehr als ein return,

Code: Alles auswählen

try: 
    return expression
except Error1:
    return expression
except Error2:
    return expression

#oder 

try:
    result = expression
except Error1:
    result = expression
#...
return result

#oder sogar 
try:
#...
finally:
    return result
bzw.

Code: Alles auswählen

if expression:
    return "Hello World"
else:
    return "Hello"

#oder 
if expression:
    return "Hello World
return "Hello"
Wie sieht es hier aus ?

Code: Alles auswählen

if bool_ == False:
    ...

#oder 

if not bool:
    ...
und hier ?

Code: Alles auswählen

text = "...."
text += "...."
if expression:
    text += "...."
return text

#oder
text1 = ".."
if expression:
    text2 = "...."

return "....%s.... \ 
          ....%s" % (text1, text2)

#oder 
return "....{0}....{1}...".format(text1, text2)
Wie sieht es bei Parameterköpfen aus wenn sie doch mal etwas größer werden.

Code: Alles auswählen

# im beispiel jetzt etwas kleiner
def func(a, b, c, d="", e=[]):
    ...

#so ?
def func ( a,
           b,
           c,
           d = "",
           e = [] )

#oder so ? - also bis erste Zeile voll
def func ( a, b, c,
           d="", e=[] )

#oder andere ?
dazu nochmal die noch hier http://python-forum.de/viewtopic.php?f= ... 7&start=15 offene Frage.
Wann *, ** als Parameter nutzen ?
bzw ist das wirklich nur eine reine Style-Frage ?

Also bei sowas zB.

Code: Alles auswählen

def func(**kw):
     ...

#oder dann doch so
def func(kw={})
    ...
bzw das selbe bei Listen oder gemischt.

Wie siehts mit default Werten aus ?
Besser immer setzen oder nur bei absoluter Notwendigkeit, zB. lohnt sich so was oder wäre es besser das None wegzulassen.

Code: Alles auswählen

def __init__(self, master=None):
     ...
Ich hätte noch mehr solcher Sachen, aber ich will es erstmal dabei belassen :mrgreen:
und was meint ihr ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Meine Präferenzen wären:

Code: Alles auswählen

return "Hello World" if expression else "Hello"

Code: Alles auswählen

if not bool_: ... 
Mehrzeilige Parameterlisten finde ich persönlich unübersichtlich. Solange es <80 Zeichen sind, kommt alles in eine Zeile und sonst halt ein Zeilenumbruch.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

1. In dem Fall definitiv den KeyError fangen, der test kostet unnötig Zeit.
2. Da läuft man schnell Gefahr schwer lesbaren Code zu schreiben aber ich würde erstmal die erste Variante nehmen.
3. Definitiv letzteres.
4. In keiner Sprache ist == True/False eine gute Idee.
5. Hängt von der Anzahl der Bedingungen ab, prinzipiell ist string formatting zu bevorzugen, ansonsten listen verwenden und joinen.
6. Zum einen sollten Klammern *nie* mit Leerzeichen umgeben sein, es sei den man hat sowas wie ``a * (b + c)`` und auch dann nur ein Leerzeichen zwischen Klammer und Operator. Natürlich hält man die maximale Zeilenlänge ein, damit fällt ersteres weg, zweiteres sowieso die Einrückung ist total unsinning und verwirrend und drittes macht ebenfalls nicht viel Sinn. Ich würde umbrechen und in der nächsten Zeile auf Höhe der öffnenden Klammer beginnen.
7. Nein, sowas ist keine Style Frage. Ersteres schränkt dich für die Zukunft ein, sollte also vermieden werden wenn dies ein Problem werden könnte.
8. Kann man ohnehin nicht immer setzen.

Übrigens sollte man veränderbare Objekte nicht als default Werte nehmen, die Signatur wird nur einmal evaluiert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

DasIch hat geschrieben:1. In dem Fall definitiv den KeyError fangen, der test kostet unnötig Zeit.
Stimmt so nicht.
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

DasIch hat geschrieben:Übrigens sollte man veränderbare Objekte nicht als default Werte nehmen, die Signatur wird nur einmal evaluiert.
Grundsätzlich stimme ich zwar zu, aber nachdem mich pylint gestern angemotzt hat: es gibt Ausnahmen. e.g:

Code: Alles auswählen

from collections import defaultdict
class MyDict(defaultdict):
    def __init__(self, adict={}):
        defaultdict.__init__(self, adict)
        ...
    ...
adict wird weder von MyDict.__init__ noch von defaultdict.__init__ verändert, deswegen halte ich es besser, das wie oben zu programmieren, anstatt so:

Code: Alles auswählen

    def __init__(self, adict=None):
        if adict is None:
            adict = {}
        defaultdict.__init__(self, adict)
        ...
    ...
[EDIT]

Andererseits ist die beste Lösung vielleicht:

Code: Alles auswählen

    def __init__(self, adict=()):
        defaultdict.__init__(self, adict)
Zuletzt geändert von pillmuncher am Mittwoch 27. Oktober 2010, 14:15, insgesamt 1-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

numerix hat geschrieben:
DasIch hat geschrieben:1. In dem Fall definitiv den KeyError fangen, der test kostet unnötig Zeit.
Stimmt so nicht.
Womit der Grundstein für eine unserer beliebten Meta-Diskussionen erfolgreich gelegt wäre :lol:

Warum stimmt das so nicht? Unter welchen Voraussetzungen gilt anderes? Gilt das überhaupt?
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@numerix und @DasIch 8.
Ähm bitte mit begründen, sonst hat der Thread wohl keinen sinn

@DasIch 7.
Detallierter bitte :(

6.
Zu dem Einrutschen mit den Funktion war ein Fehler vom automatischen einrücken jetzt sind sie so wie es gemeint war.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

pillmuncher hat geschrieben: [EDIT]

Andererseits ist die beste Lösung vielleicht:

Code: Alles auswählen

    def __init__(self, adict=()):
        defaultdict.__init__(self, adict)
und wie siehts aus wenn ich dann doch wirklich eine Dictionary erwartet wird, also damit in der Funktion gearbeitet wird ?
Aber nur ein tuple als default gesetzt ist und ich als anwender davon ausgehe das nur ein tuple benötigt wird, ist das dann nicht etwas kontra produktiv?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Xynon1 hat geschrieben:@numerix und @DasIch 8.
Ähm bitte mit begründen, sonst hat der Thread wohl keinen sinn
Wie DasIch darauf kommt, weiß ich nicht. Dass es - zumindest in dieser allgemein gültigen Form - nicht stimmt, lässt sich leicht feststellen, indem man es ausprobiert.
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Xynon1 hat geschrieben:und wie siehts aus wenn ich dann doch wirklich eine Dictionary erwartet wird, also damit in der Funktion gearbeitet wird ?
Aber nur ein tuple als default gesetzt ist und ich als anwender davon ausgehe das nur ein tuple benötigt wird, ist das dann nicht etwas kontra produktiv?
Deswegen heißt der Parameter adict. Außerdem sollte man docstrings schreiben, dann kann man nachlesen, was für Parameter erwartet werden.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich stell gleich mal noch ein paar Fragen, nicht das es noch langweilig wird :D

Code: Alles auswählen

x = 0
try:
    anything / x
except ZeroDivisionError:
    print(u"nicht m\xf6glich")

#oder
if x != 0:
    anything / x

#oder
if not(x == 0):
    anything / x
Dann wie definiert man am besten "manuell" eine Dictionary.

Code: Alles auswählen

d = dict(a=1, b=2, c=3)

#oder
d = {"a":1, "b":2, "c":3}
Wie die Parameter Listen iteriert füttern ?
Also auf das Beispiel von http://python-forum.de/viewtopic.php?f=1&t=24501

Code: Alles auswählen

def __init__(self, name="", year=0, sex=NEUTER):
    ...

Person(*data)

#oder so besser ?

Person(data[0], data[1], data[2])
@pillmuncher
Stimmt.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Xynon1:
1) Die erste Variante, oder:

Code: Alles auswählen

if x:
    anything / x
2) Beides ist ok. Die erste Variante ist zwar kürzer, hat aber Probleme:

Code: Alles auswählen

d = dict(1=2, 3=4, 5=6)
ist kein gültiges Python, im Gegensatz zu

Code: Alles auswählen

d = {1:2, 3:4, 5:6}
3) Die erste Variante, oder:

Code: Alles auswählen

name, year, sex = data
Person(name, year, sex)
wenn es explizit sein soll.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

IMHO macht es mehr Sinn mehrere Threads auf zu machen, statt zu viele Fragen hier gleichzeitig zu klären ;)

Zum Thema "lieber try...except oder mit if arbeiten": If ist schneller, wenn die "Ausnahme" ehr die Regel ist. Ein Vorteil von Exceptions allgemein ist der, das man Fehler erst später verarbeiten kann, bzw. man kann mehrere Fehler auf einmal abfangen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Mit anderen Worten ich hätte 5 - 10 Threads öffnen sollen deswegen ? :shock:
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

jens hat geschrieben:Zum Thema "lieber try...except oder mit if arbeiten": If ist schneller, wenn die "Ausnahme" ehr die Regel ist.
Das "eher" müsste man noch etwas geringer ansetzen. Je nach konkretem Code tritt dieser Fall (dass if schneller ist als die Ausnahme abzufangen) schon dann ein, wenn der Anteil der Ausnahmefälle bei 10% liegt. Ich würde darum sagen: Das Abfangen der Ausnahme ist nur dann schneller, wenn der Anteil der auftretenden Ausnahmen ziemlich gering ausfällt. Schon bei einem Anteil von rund 50% ist das Abfangen der Ausnahme um ein Vielfaches langsamer.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Was sollte man eigentlich machen, wenn man mehrer Datentypen direckt nutzen möchte.
Ich spiele darauf an sowohl eine Dictionary, List, Tuple und Objekte zu nutzen in einer Funktion.
Also zB.:

Code: Alles auswählen

def func(data):
    data.name
    data["name"]
    data[0]

class data(object):
     name = "hw"

instanz = data()

func(instanz)
func(dict(name="hw"))
func(["hw",])
func(("hw",))
Natürlich geht das jetzt nicht, aber sollte man die Fälle mit try...except...
Abfangen, oder auf typ prüfen(was ich eher als unschön empfände) oder gibt es andere Möglichkeiten.

Nur nebenbei, bin gerade dabei meine "älteren"(auch neuere) Scripte mal aufzuräumen, funktionieren tut alles nur der Stil lässt zum Teil echt zu Wünschen übrig. Deswegen die ganzen Fragen, damit sich endlich mal eine einheitliche Strucktur durch zieht.
Denn das ist bei den meisten Tutorials unmöglich und zum Teil richtig Falsch. Und in der Python Documentation stehen solche Fälle selten ausführlich Beschrieben drin.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

ich habe das bisher zwar nur sehr wenig gebraucht, aber bisher so gelöst:
Da muss es doch auch was besseres geben ?!

Code: Alles auswählen

def func(data):
    try:
        data.name
    except AttributeError:
         try:
             data[0]
         except (TypeError, IndexError, KeyError):
             try:
                 data["name"]
             except:
                 raise Warning
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@Xynon1: Ich würde sagen man sollte nicht so eine API haben, bei der `data` so viele verschiedene "Dinge" sein kann.
lunar

DasIch hat geschrieben:4. In keiner Sprache ist == True/False eine gute Idee.
Das stimmt im Übrigen auch nicht, sondern hängt von der Sprache ab. Das nur als Anmerkung.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

mh, was haltet ihr von follgendem:

Code: Alles auswählen

class Data:
    def __init__(self):
         self.name = ""
    #...
    def __iter__(self):
        yield self.name
        #yield attr2

# statt
def func(data):
    try:
        data.name
    except AttributeError:
         try:
             data[0]
         except (TypeError, IndexError, KeyError):
             try:
                 data["name"]
             except:
                 raise Warning

#diese hier:

def func(data):
    try:
        [name for name in data.values()]
    except AttributeError:
        [name for name in data]
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten