Funktionen innerhalb von Funktionen

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
n3xtplayer
User
Beiträge: 36
Registriert: Sonntag 2. Oktober 2011, 12:13

Dienstag 18. Oktober 2011, 15:08

Und schon wieder habe ich ein Problem und komme nicht mehr weiter. Heute ist wohl nicht mein Tag...
Ich versuche vergebens eine Funktion in einer anderen aufzurufen. Habe schon alles gegoogelt und ausprobiert, irgendwas ist jedoch immer falsch.
Die erste Funktion:

Code: Alles auswählen

def Deck1(Basic_Deck = [2,3,4,5,6,7,8,9,10,10,10,10,11]):
	D = 24*Basic_Deck
Und wenn ich sie in der zweiten

Code: Alles auswählen

def Deck2(x =7):
	Deck1()
	random.shuffle(D)
	for i in range(x):
		print(D[0])
versuche zu öffnen, kommt immer diese Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "<pyshell#128>", line 1, in <module>
    Deck2()
  File "<pyshell#127>", line 3, in Deck2
    random.shuffle(D)
  File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py", line 263, in shuffle
    for i in reversed(range(1, len(x))):
TypeError: object of type 'int' has no len()
das verstehe ich jedoch nicht, denn D sollte doch nun sehr wohl eine ''len'' haben?
Btw. das ist nur ein Beispiel also vergesst den Rest :P
Jemand eine Idee? LG
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 15:12

Deine Fehlermeldung passt nicht zum Code!

Code: Alles auswählen

In [54]: Deck2()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/nelson/src/Python/forum/<ipython console> in <module>()

/home/nelson/src/Python/forum/<ipython console> in Deck2(x)

NameError: global name 'D' is not defined
So kannst Du es also nicht probiert haben...

Generell solltest Du Funktionsnamen nicht groß schreiben, sondern klein_mit_underscore. (s. PEP8).

Deine Funktionen geben niemals etwas zurück:

Code: Alles auswählen

In [69]: def foo(bar):
   ....:     return bar*2
   ....: 

In [70]: foo(3)
Out[70]: 6

In [71]: foo(42)
Out[71]: 84

In [72]: def test():
   ....:     print 10 + foo(2)
   ....:     
   ....:     

In [73]: test()
14
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Dienstag 18. Oktober 2011, 15:17

Was ist den "D"? Jedenfalls nicht dasselbe in "Deck2" wie "Deck1". "Deck1" hat keinen Rückgabewert - außer "None". Wenn man die Funktionen so definiert und dann einfach aufruft sollte man "NameError: global name 'D' is not defined" erhalten und nicht Deine Fehlermeldung.

Tipps:
- Gebe in Deck1() etwas zurück.
- Die Tatsache, dass Du in Deck1 etwas an D bindest bedeutet nicht, das D überall bekannt ist - im Gegenteil.
- Verwende die "range()"-Funktion nicht um x-Mal dasselbe auzugeben.
- Schau Dir mal Pep8 an, denn der Code liest sich reichlich seltsam und - sorry - das werde ich nicht einfach "vergessen" ;-)
- Quasi-Konstante Listen solltest Du vielleicht nicht in Funktionen, sondern im Kopf des Moduls oder extern definieren.

HTH
Christian

edit: Mist, zu langsam ;-)
n3xtplayer
User
Beiträge: 36
Registriert: Sonntag 2. Oktober 2011, 12:13

Dienstag 18. Oktober 2011, 15:41

Also zuerst ein mal: wenn ich Deck2() eingebe, dann bekomme ich genau diese Fehlermeldung. Dass ihr sie nicht bekommt macht das ganze um so verwirrender... vielleicht ist das weil ich mit IDLE arbeite?!?!
Also meine Idee war einfach, ein Deck mit dem alias D in einer Funktion zu definieren und dann in einer anderen Funktion weiter zu verwenden. Das D wäre also doch in beiden Funktionen das gleiche... Ich habe nun versucht, einfach ''return(D)'' ans Ende von ''Deck1'' zu hängen, es kommt jedoch immer noch die gleiche Fehlermeldung. Keine Ahnung was da falsch läuft....
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 15:54

n3xtplayer hat geschrieben:Also zuerst ein mal: wenn ich Deck2() eingebe, dann bekomme ich genau diese Fehlermeldung. Dass ihr sie nicht bekommt macht das ganze um so verwirrender... vielleicht ist das weil ich mit IDLE arbeite?!?!
Du hast in der Shell von idle wohl noch ein Objekt namens `D` definiert?
Also meine Idee war einfach, ein Deck mit dem alias D in einer Funktion zu definieren und dann in einer anderen Funktion weiter zu verwenden. Das D wäre also doch in beiden Funktionen das gleiche... Ich habe nun versucht, einfach ''return(D)'' ans Ende von ''Deck1'' zu hängen, es kommt jedoch immer noch die gleiche Fehlermeldung. Keine Ahnung was da falsch läuft....
`return` ist keine Funktion, sondern ein Statement. Du solltest daher die Klammern weglassen. Du musst nicht nur in der ersten Funktion das Objekt zurückgeben, sondern die Rückgabe auch in der zweiten weiterverarbeiten! Schau Dir doch mal meine Beispiel genau an ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
n3xtplayer
User
Beiträge: 36
Registriert: Sonntag 2. Oktober 2011, 12:13

Dienstag 18. Oktober 2011, 16:19

Ok du hast recht, habe es jetzt verstanden. Der Aufruf des Funktionsnamens() ist gleichbedeutend mit dem Ausgabewert.
Ich muss dich jedoch korrigieren, die Klammern sind nötig :) Arbeite mit Mac und IDLE, und egal ob print oder return, ohne Klammern läuft da gar nix.
Danke für die Hilfe! Lg, Camill
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Dienstag 18. Oktober 2011, 16:26

Nein!

- Funktionsnamen werden nicht aufgerufen, sondern nur Funktionen.
- Der Aufruf von Funktionen ist nicht gleich ihrem Rückgabewert! Wie kommst Du darauf? Das Eine hat nur bedingt etwas mit dem Anderen zu tun.
- Klammern bei return sind in der Tat nicht notwendig. Wenn doch machst Du etwas Anderes als Du uns zeigst. Zeige bitte mal den Code, der die Klammern notwendig macht - und zwar ein vollständiges Minimalbeispiel. Weil sonst läuft das was ziemlich schief.
- Den Rückgabewert einer Funktion solltest Du an ein Objekt binden (direkt an einen Namen oder einer Liste hinzufügen, etc.) - es sei denn er wird wirklich nicht benötigt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 16:27

n3xtplayer hat geschrieben:Ok du hast recht, habe es jetzt verstanden. Der Aufruf des Funktionsnamens() ist gleichbedeutend mit dem Ausgabewert.
Diese "Erklärung" habe ich jetzt nicht verstanden. Funktionen sind doch genauso wie in der Schulmathematik zu verstehen: Du kannst etwas "reinwerfen", das wird innerhalb der Funktion verarbeitet und am Ende wird etwas zurückgegeben. Um eine Funktion zu nutzen, muss man sie eben aufrufen.
Ich muss dich jedoch korrigieren, die Klammern sind nötig :) Arbeite mit Mac und IDLE, und egal ob print oder return, ohne Klammern läuft da gar nix.
Die Sprache Python ist standardisiert - daher ist die Syntax und Semantik nicht vom OS oder gar einer Shell abhängig. Wenn `print` bei Dir "Klammern" benötigt, dann ist es eben eine Funktion. Dies ist seit Python 3.0 der Fall; insofern liegt es an der von Dir verwendeten Python-Version. Bei 2.x ist print ein Statement und daher keine Klammern sinnvoll.

`return` hingegen ist auch bei Python3 noch ein Statement und daher sind dort Klammern überflüssig!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
n3xtplayer
User
Beiträge: 36
Registriert: Sonntag 2. Oktober 2011, 12:13

Dienstag 18. Oktober 2011, 16:56

Ok ok ok ok ok ich verstehe schon, alles falsch. Ihr habt natürlich recht, return benötigt auch bei mir keine Klammern.
Den Rückgabewert an ein Objekt binden habe ich schon gemacht. Aber keine Angst, jetzt wo ich sehe wie viel ich noch falsch verstanden habe, werde ich sicher bald wieder eine Frage haben, denn es dauert noch ein wenig bis meine Arbeit beendet ist :)
Mfg
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dienstag 18. Oktober 2011, 17:06

n3xtplayer hat geschrieben: Den Rückgabewert an ein Objekt binden habe ich schon gemacht.
Genau genommen ist der Rückgabewert ein Objekt und Du bindest ihn so

Code: Alles auswählen

a = foo()
an einen Namen. Das hat CM unpräzise dargestellt. Er wollte darauf hinaus, dass man den Rückgabewert auch direkt in eine Collection aufnehmen kann:

Code: Alles auswählen

a = list()
a.append(foo())
Du kannst letztlich alles damit machen, was Du auch mit einem direkt vorhandenen Objekt an dieser Stelle machen kannst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Mittwoch 19. Oktober 2011, 07:57

Danke - da war ich in der Tat etwas nachlässig.
Antworten