return aus Funktion übergibt nicht gewünschten Wert ?

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
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Das verstehe ich nicht ? Es wird die erste gebildete Liste übergeben. Warum nicht die letzte erzeugte ?

Code: Alles auswählen

import random
a = list()

def erzeuge(a):
    while True:
        for x in range (9):  
            a.append(random.randint(1,9))
        if len(set(a)) < 9:
            a = list()
            continue
        print a
        return a 
        break
  
    
erzeuge(a)
print a
gruss und dank frank
Actimehl
User
Beiträge: 6
Registriert: Donnerstag 7. September 2006, 14:37

Macht dieser Code das, was du willst?
Das Problem liegt darin wie Namen an Objekte gebunden werden.

Code: Alles auswählen

import random
b = list()

def erzeuge(a):
    while True:
        for x in range (9): 
            a.append(random.randint(1,9))
        if len(set(a)) < 9:
            a = list()
            continue
        print a
        return a
        break
 
   
print erzeuge(b)
print b
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Mein code macht was es will - nein, er macht schon was ich möchte. Er erzeugt eine Liste mit Zufallszahlen. Damit diese Liste keine doppelten Einträge erhält mache ich das mit dem set(). Doch übergebe ich diese Liste, kommt nicht die Liste mit den unterschiedlichen Zufallszahlen raus, sondern die erste Liste, die beim Start erzeugt wird.

Code: Alles auswählen

import random
a = list()

def erzeuge(a):
    while True:
        for x in range (9):  
            a.append(random.randint(1,9))
        print a
        if len(set(a)) < 9:
            a = list()
            continue
        print a
        return a 
        break
  
    
erzeuge(a)
print a
so kann man es auch machen und vergleichen.

Code: Alles auswählen

import random
a = list()

def erzeuge(a):
    while True:
        for x in range (9):  
            a.append(random.randint(1,9))
        if len(set(a)) < 9:
            a = list()
            continue
        print a
        ausgabe(a)
        break
  
def ausgabe(a):
    print a
    
erzeuge(a)
so geht es jetzt ?

gruss und dank frank
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

kaytec hat geschrieben:Mein code macht was es will - nein, er macht schon was ich möchte. Er erzeugt eine Liste mit Zufallszahlen. Damit diese Liste keine doppelten Einträge erhält mache ich das mit dem set(). Doch übergebe ich diese Liste, kommt nicht die Liste mit den unterschiedlichen Zufallszahlen raus, sondern die erste Liste, die beim Start erzeugt wird.
Also zumindest im ersten Quelltext konnte ich dein Problem nicht nachvollziehen. Das einzige was ich gesehen habe ist, dass er ziemlich unperformant ist. Stell dir vor, die Länge des sets beträgt die ersten 2000 male acht statt neun. Dann wird die ``while``-Schleife 2001 Mal durchlaufen, bis eine passende Sequenz gefunden wurde.

Davon abgesehen, gibt es für sowas ``random.shuffle()``:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import random

random_numbers = range(1, 10)
random.shuffle(random_numbers)
print random_numbers
Finde ich jetzt ein wenig lesbarer. Die Zahlen kommen nie doppelt vor, dafür ist automatisch gesorgt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Danke Leonidas !

Mein code ist Trail and Error - ok, hast schon recht. Warum verhält sich die Liste a bei der Übergabe so?

gruss und dank frank
BlackJack

In Deinem ersten Quelltext wird ausserhalb der Funktion eine Liste erzeugt und an den Namen `a` im Namensraum des Moduls gebunden. In der Funktion wird diese Liste an den lokalen Namen `a` gebunden und mit Werten gefüllt. Beide Namen verweisen auf das selbe `list`-Objekt. Wenn die Liste nicht den Bedingungen entspricht, wird in der Schleife eine *neue* Liste erzeugt und an den lokalen Namen `a` gebunden. Der Name im Modul verweist immer noch auf das zuerst gefüllte `list`-Objekt!

Am Ende des Quelltextes wird die Funktion aufgerufen und mit dem Rückgabewert wird nichts gemacht! Und danach wird die Liste ausgegeben, die an `a` gebunden ist. Also die erste "Befüllung".
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Jetzt habe ich es glaub ich verstanden - ich hätte schreiben müssen:

Code: Alles auswählen

ausgabe = erzeuge()
print ausgabe
gruss frank
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Habe mal den gleichen Fehler in die neue Funktion eingebaut. Ich erzeuge die Liste a und verändere sie lokal in der Funktion. Global ist sie aber noch als 'leere' Liste vorhanden. Diese Liste wird dann auch so ausgegeben ?

Code: Alles auswählen

import random
a = list()
def erzeuge(a):
    random_nummer = range(1, 10)
    random.shuffle(random_nummer)
    a = random_nummer
    return a

b = erzeuge(a)
print a
print b
gruss und dank frank
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

kaytec hat geschrieben:Habe mal den gleichen Fehler in die neue Funktion eingebaut. Ich erzeuge die Liste a und verändere sie lokal in der Funktion. Global ist sie aber noch als 'leere' Liste vorhanden. Diese Liste wird dann auch so ausgegeben ?
Natürlich wird die die modulglobale Liste unter dem Namen ``a`` nicht verändert. Wenn du zu ``a`` etwas in einem Funktionsscope (Namensraum) zuweist, wird die globale Variable "überdeckt" und nicht überschrieben. Dies ist das Standardverhalten von Python und es ist auch gut so. Es gibt aber die Möglichkeit Globale Variablen zu überschrieben: sollte man aber wirklich, wirklich nur in Ausnahmefällen tun! Das macht das Programm wesentlich weniger verständlich.

So sieht es mit überschreiben globaler Variablen aus:

Code: Alles auswählen

import random
a = list()
def erzeuge():
    global a
    random_number = range(1, 10)
    random.shuffle(random_number)
    a = random_number
    return a

b = erzeuge()
print a
print b
Übrigens, so etwas geht auch:

Code: Alles auswählen

import random
a = list()
def erzeuge(a):
    random_number = range(1, 10)
    random.shuffle(random_number)
    a.extend(random_number)

erzeuge(a)
print a
Da ``a`` eine Liste ist und Listen mutabel (also veränderlich) sind, kann man an sie etwas anhängen, ohne ``global`` Schlüsselwort. Das liegt daran, dass im ersten Code die Liste ``a`` mit einer neuen Liste überschrieben wird und im zweiten Beispiel wird an die Liste a nur etwas drangehängt - ohne eine neue Liste zu erstellen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@kaytec: Du veränderst die übergebene Liste nicht in der Funktion, Du erzeugst eine völlig neue Liste und gibst der den lokalen Namen `a`. Selbst bei einem ``global a`` am Anfang Deiner Funktion würde die ursprüngliche Liste nicht verändert, sondern ersetzt. Wäre sie noch auf anderem Wege erreichbar, weil sie zum Beispiel noch an einen anderen Namen gebunden wäre, dann würde dort immer noch eine leere Liste ansprechbar sein.
Antworten