Variable an Funktion und wieder zurück...

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

ich bin totaler Python-Newbie und hänge an folgendem Problem:

Ist es möglich, die Variable a an eine Funktion zu übergeben, dort zu bearbeiten, wieder zurückzugeben, auszuwerten um dann wieder an dieselbe Funktion zu übergeben und so weiter...

Hier der Code, der so nicht funktionieren will:

Code: Alles auswählen

#!/usr/bin/python
a=0

def aplus(a):
	a=a+1
	return a
	

while a<5:
	print aplus(a)

print 'Fertig'
Eigentlich sollte ich als Ausgabe

1
2
3
4
5
Fertig

erhalten, stattdessen erhalten ich endlos

1
1
1
...

Vielleicht bin ich einfach auch zu blöde für solche Sachen und sollte lieber Vogelhäuschen basteln....

Trotzdem würde ich mich über einen Tipp freuen!

Liebe Grüße
    Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
    Benutzeravatar
    helduel
    User
    Beiträge: 300
    Registriert: Montag 23. Juli 2007, 14:05
    Wohnort: Laupheim

    Moin mutetella,

    du definierst a=0 am Anfang und in deiner while-Schleife übergibst du immer diese 0 and die Funktion. Dort wird 1 addiert und zurückgegeben. Das gibst du mit print aus. Der Wert von a ändert sich hier aber nicht. Das tut a nur innerhalb der Funktion aplus. Du kannst ja mal die as in aplus zu in b umbenennen, dann wird vielleicht klarer, was da abgeht.

    Damit es funzt, muss du das machen:

    Code: Alles auswählen

    a=0
    
    def aplus(a):
        a=a+1
        return a
       
    
    while a<5:
        a = aplus(a) # errechneter Wert wird a zugewiesen
        print a
    
    print 'Fertig'
    Gruß,
    Manuel
    Benutzeravatar
    cofi
    Python-Forum Veteran
    Beiträge: 4432
    Registriert: Sonntag 30. März 2008, 04:16
    Wohnort: RGFybXN0YWR0

    Damit dir Funktionen klarer werden, denk mal darüber nach:

    Code: Alles auswählen

    def increment(x):
        x = x + 1
        return x
    
    a = 0
    while a < 5:
        a = increment(a)
    
    print a
    Ansonsten: 1x Tutorial durcharbeiten, bitte.
    mutetella
    User
    Beiträge: 1695
    Registriert: Donnerstag 5. März 2009, 17:10
    Kontaktdaten:

    Hallo,

    was hab' ich nicht alles gelesen und bekam dabei mehr und mehr das Gefühl, gar nichts mehr zu verstehen... :x

    Danke für Eure Beiträge, jetzt ist es eigentlich klar wie Brühe!!

    Das ist zwar jetzt sehr theoretisches Gefasel, aber für mich wäre nochmal wichtig:
    Kann man sagen, dass die Variable a in der Funktion aplus() eine andere Variable als Variable a im Hauptblock ist. Auch wenn beide a heißen? Denn wenn ich den Code von cofi anschaue, dann wird a aus dem Hauptblock erstmal an x übergeben, dort verarbeitet und über return wieder an a zum Hauptblock zurückgegeben.
    Wenn mein Gedanke so richtig ist, gäbe es denn dann auch eine Lösung, die nicht Variablenwerte, sondern die Variablen selbst übergibt.
    Ich hatte schon versucht, a innerhalb der Funktion aplus(), an die ich a übergab, zur globalen Variable zu erklären, bekam aber dann die Fehlermeldung, dass a sowohl local als auch global sei.

    Nochmals danke für Eure Hilfe...

    Liebe Grüße
    Claus

    P.S.: Es ist nicht so, dass ich mich nicht durch verschiedenste Tutorials durchquäle, aber mein english is so horrible und gute deutsche Python Anleitungen sind echt sehr rar.... Ja ja, ich weiß, programmieren wollen aber nicht gescheit Englisch können.... :wink:
    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:

    mutetella hat geschrieben: Kann man sagen, dass die Variable a in der Funktion aplus() eine andere Variable als Variable a im Hauptblock ist. Auch wenn beide a heißen?
    Ja! :-)
    BlackJack

    Und nein, man kann keine "Variable" übergeben, sondern immer nur Objekte.
    Benutzeravatar
    Hyperion
    Moderator
    Beiträge: 7478
    Registriert: Freitag 4. August 2006, 14:56
    Wohnort: Hamburg
    Kontaktdaten:

    BlackJack hat geschrieben:Und nein, man kann keine "Variable" übergeben, sondern immer nur Objekte.
    Von übergeben stand da doch nichts? (Also in meinem Quote ;-) )
    Benutzeravatar
    cofi
    Python-Forum Veteran
    Beiträge: 4432
    Registriert: Sonntag 30. März 2008, 04:16
    Wohnort: RGFybXN0YWR0

    Na wenn wirs schon ganz genau nehmen, dann muss man darf man das auch nicht Variable nennen, denn es gibt nur Namen, die dann als Referenzen zu Objekten dienen. ;)
    mutetella
    User
    Beiträge: 1695
    Registriert: Donnerstag 5. März 2009, 17:10
    Kontaktdaten:

    Alles klar, ich stehe da schon auch mehr auf genaue Benennung der Dinge :D :

    Es ist also so, dass das Objekt a anfangs 0 ist, d. h. eine 0 enthält (oder so...). Übergebe ich mit aplus(a) nun das Objekt a oder den Wert 0? Wenn ich bisher richtig gefolgt bin, übergebe ich doch den Wert, der im Objekt a steht, oder?

    Nochmals meine Frage: Wenn das bisher so stimmt, gibt es dann eine Möglichkeit, nicht nur den Wert, sondern das Objekt, das den Wert enthält, zu übergeben und auch wieder zurückzubekommen?

    Oder ist das totaler Schwachsinn, braucht kein Mensch und daher sollte auch keine Energie in solche Überlegungen gesteckt werden?

    Liebe Grüße
    Claus
    Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
    Nocta
    User
    Beiträge: 290
    Registriert: Freitag 22. Juni 2007, 14:13

    a ist afaik auch kein Objekt sondern nur ein Name für ein Objekt.
    Das Objekt an sich ist das int-Objekt, für das a eine Referenz darstellt oder so.
    a = b = 5 heißt ja auch nicht, dass a und b ein Objekt sind. Sie sind beide Referenzen auf das Objekt int(5).
    Du übergibst, wenn du die Funktion aufrufst keine Referenz auf das Objekt sondern eine Kopie des Objekts, wodurch es ein neues Objekt ist und nichts mit dem anderem Objekt zu tun hat.
    So hab ich das bisher immer verstanden und ich hoffe mal, dass ich da jetzt nicht ganz falsch liege ;)
    Benutzeravatar
    cofi
    Python-Forum Veteran
    Beiträge: 4432
    Registriert: Sonntag 30. März 2008, 04:16
    Wohnort: RGFybXN0YWR0

    Stimmt nicht ganz. Du hast ein Objekt mit dem Namen a. Das ist deshalb wichtig, da a ein ganz anderes Objekt referenzieren kann, ohne dass das ursprüngliche Objekt zerstört wird (durch den GC), sofern eine andere Referenz gehalten wird ;)

    Es wird immer das Objekt übergeben, es wird nur ein anderer Namen drübergeklebt. Da Zahlen unveränderbar sind, eignen die sich nicht sonderlich um das zu demonstrieren, Listen aber schon:

    Code: Alles auswählen

    In [3]: a = [1,2,4]
    In [4]: def manipulate(victim):
        victim += [42]
        return victim
    
    In [7]: b = manipulate(a)
    
    In [8]: a
    Out[8]: [1, 2, 4, 42]
    
    In [9]: b
    Out[9]: [1, 2, 4, 42]
    Darii
    User
    Beiträge: 1177
    Registriert: Donnerstag 29. November 2007, 17:02

    mutetella hat geschrieben:Wenn mein Gedanke so richtig ist, gäbe es denn dann auch eine Lösung, die nicht Variablenwerte, sondern die Variablen selbst übergibt.
    Nein, sowas (C++-Referenzen) gibt es in Python nicht, wenn du so etwas *wirklich* brauchst, kannst du es mit einem Dummy-Objekt oder einer Liste emulieren.

    Code: Alles auswählen

    a = [0]
    def inc(b):
        b[0] += 1
        return b
    while a[0] < 5:
        print inc(a)[0]
    
    DasIch
    User
    Beiträge: 2718
    Registriert: Montag 19. Mai 2008, 04:21
    Wohnort: Berlin

    cofi hat geschrieben:Stimmt nicht ganz. Du hast ein Objekt mit dem Namen a.

    Code: Alles auswählen

    In [1]: a = 5
    
    In [2]: a.__name__
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    
    /home/dasich/<ipython console> in <module>()
    
    AttributeError: 'int' object has no attribute '__name__'
    `a` ist ein Name/Referenz auf 5 aber 5 hat keinen Namen. Namen haben nur Funktionen/Methoden und Klassen.

    P.S.:Anonyme Funktionen haben natürlich ebenfalls keine Namen.
    Leonidas
    Python-Forum Veteran
    Beiträge: 16025
    Registriert: Freitag 20. Juni 2003, 16:30
    Kontaktdaten:

    Und um das noch genauer herauszustellen: Objekte wissen ihre "Namen" gar nicht. D.h. sie können einen Namen haben (der Regelfall), ganz viele oder auch gar keine (Elemente einer Liste sind z.B. oftmals anonym).

    Und das das ``a`` verschieden ist liegt daran dass es verschiedene Sichtbarkeits/Gültigkeitsbereiche aka Scopes gibt.
    My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
    jerch
    User
    Beiträge: 1669
    Registriert: Mittwoch 4. März 2009, 14:19

    Einfacher lässt sich das Ganze mit Blick auf die Datentypen hinsichtlich mutable/immutable verstehen und man bedenkt, daß Python eigentlich immer call by reference macht. Foldendes kleines Bsp:

    Code: Alles auswählen

    a = b = 0
    print id(a)
    print id(b)
    def bla(x):
        print id(x)
        x += 1 # hier greift das immutable von Zahlentypen
        print id(x)
        return(x)
    a = bla(a)
    print id(a)
    Das immer call by refence gemacht wird, sieht man an den gleichen ids in Zeile 2, 3 und 5. Zeile 6 macht nun den Unterschied für mutable/immutable aus.

    immutable:
    Eine Operation an einen immutable Objekt erzeugt im Hintergrund ein neues Objekt mit dem neuen Wert, dieses Objekt wird anschließend x zugewiesen. Daher ändert sich die id. Im weiteren werden aber wieder nur "Refenzen" übergeben, siehe ids in zeile 7 und 10.

    mutable:
    Für mutable Objekte fällt eigentlich nur die neue Objekterzeugung während der Operation weg, es wird also auf dem selben Objekt weitergearbeitet und alle ids bleiben gleich. Daher muß man hier eben spezielle copy()-Funktionen bedienen, um neue Objekte zu erhalten, ein einfaches b=a reicht da nicht.

    Addendum:
    Eine Zuweisung im klassischen Sinne gibt es Python nicht, vielmehr bedeutet der = Operator "verknüpfe den Bezeichner links mit dem Objekt rechts", es wird halt ein Refenzlink auf das sowieso schon bestehende Objekt rechts erstellt.
    BlackJack

    Jetzt geht das wieder los. :-)

    Python macht kein "call by reference", sondern "call by object" oder "call by sharing".

    Die Unterscheidung "call by reference" vs. "call by value" macht nur Sinn bei Sprachen, die auch Zeigerdatentypen haben.
    jerch
    User
    Beiträge: 1669
    Registriert: Mittwoch 4. März 2009, 14:19

    @BlackJack
    Ja, recht haste. Für mich als von c++ kommend, fühlt sich das Verhalten am ehensten wie Referenzschieberei an. Zeiger brauchst hierfür nicht, da der Bezeichner ja keine eigene Speicherrepräsentation haben muß (also in der Sprache). Und für Leute von anderen Sprachen herkommend, ist call by object erstmal unverständlich.

    Aber ich wollt hier nicht ne alte Kamelle von Neuem lostreten.

    Noch eine Ergänzung hierzu:
    Um die Sache völlig zu verkomplizieren, muß man in die Python-Eingeweide abtauchen und hier macht Python call-by-value. :shock:
    Vereinfacht gesagt passiert hier folgendes. Python sucht zum gegeben Bezeichner die PyObject-id und übergibt diese dann via call-by-value. Da diese aber als Referenz zum eigentlichen PyObject fungiert, nennt sich der Spaß dann call-by-object-reference (und für mich ist das nur ein Spezialfall von call-by-reference). Der wesentliche Unterschied zu z.B. c/c++ ist hier die zusätzliche Abstraktionsschicht zwischen Bezeichner und eigentlichem Objekt in Form von Referenzen (eigentlich Pointer, aber egal). Phänomenologisch wirkt sich nun der immutable/mutable-Unterschied auf Programmlogikebene aus, da sich die einen eher wie call-by-value und die anderen wie call-by-reference verhalten. Daher wohl der Versuch, das Ganze neu zu benennen.
    Antworten