Variabele Variabeln ??? :)

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
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Code: Alles auswählen

array=["Wert1"]
array[0] = "ZuZuWeisenderWert"

# Python macht nicht:
# Wert1 = ZuZuWeisenderWert     , sondern
# array[0] = ZuZuWeisenderWert

# geht nicht, Warum???:
# print Wert1

# aber dafür:
print array[0]
Doch ich möchte gerne das die in den Arrays stehenden Werte als Variabeln benutzt werden.
Hintergrund ist das abspeichern von Variabeln in einer schleife. Denn so wie oben speichert
Python dann nicht unter dem Variabelnamen ab, sondern immer über die Laufschleife des Arrays,
also z.b. würde Python immer unter array[Laufschleife] speichern und nicht unter dem im Array
hinterlegten Wert.
Wie ist das zu realisieren? Weiß da jemand weiter?
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

hi,
Sunshine hat geschrieben:

Code: Alles auswählen

array=["Wert1"]
array[0] = "ZuZuWeisenderWert"

# Python macht nicht:
# Wert1 = ZuZuWeisenderWert     , sondern
# array[0] = ZuZuWeisenderWert

# geht nicht, Warum???:
# print Wert1

# aber dafür:
print array[0]
wenn ich das richtig verstanden habe, möchtest du sowas haben ?

Code: Alles auswählen

>>> array = {}
>>> array['wert'] = "ZuZuWeisenderWert"
>>> array
{'wert': 'ZuZuWeisenderWert'}
>>> print array['wert']
ZuZuWeisenderWert
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Hi pyStyler,

danke für die fixe antwort!
Ist aber leider nicht ganz das was ich suche. Versuche es mal anhand eines Bsp. deutlicher zu machen.

Code: Alles auswählen

from Tkinter import *

class GUI_Menue:
   def __init__(self, master):        

      # Fenster erzeugen                
      fenster_1 = Frame(master)
      fenster_1.pack(fill=X)

      global name_1, name_2, root, name
      
      eingaberahmen = Frame(root)
      eingaberahmen.pack()

      for i in range(1,3):   
         name = "name_" + `i`
         name = Entry(eingaberahmen)
         name.pack(side=LEFT)
  
      endeknopf = Button(root,	text='Fertig', command = self.ausgabe)
      endeknopf.pack(fill = BOTH, expand = 1)

      

   def ausgabe(self):
      global name_1, name_2,name
      #print name_1.get()               GEHT NICHT
      #print name_2.get()               GEHT NICHT
      print name.get()

      root.destroy()

root = Tk()
gui = GUI_Menue(root)                                                                                                   
root.title('Testprogramm') 
root.mainloop()
Python nimmt nicht die Zuweisung (name = "name_" + `i`), sondern aus der nächsten zeile nur das "name" und überschreibt es in jedem Schleifendurchlauf. Ich möchte aber das er den variabeln name_1, name_2, usw die Eingaben zuweist.
Gibt es da ne möglichkeit? Komme aus der c++ welt und da ist gang und gebe.
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Hier mal das Praxisbeispiel:

Code: Alles auswählen

# Array für die Var-Zuordnung
varnamen = ["pulvertyp", "pulverbasis", "herstellerbezeichnung"]               
min=0                                                                                                           
max_varnamen = len(varnamen)                                                                                             
for i in range(min,max_varnamen):                                                                                        
	#Entry 
	count= varnamen[i]                                                                                     
	self.count = Entry(self.frame_3, font=('MS Sans Serif', '8', 'normal'), width=30)                      
	self.count.pack(side=TOP, anchor=NW, padx=5)      
 
doch python überschreibt immer count...
grrrrrr
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi sunshine,

kenne mich nicht mit TKinter aus, aber Dein Code sieht seltsam aus (die globals).

Zu Deinem Praxisbeispiel: Das liegt daran, daß Du count ständig überschreibst. In Zeile 8 wird count zu "pulvertyp", d.h. einem String. Später weist Du der Variable dann einen neuen String zu - klar ist dann der alte überschrieben.

Bei derartigen Anwendungen arbeite ich entweder mit dicts, s. pyStylers post, oder mit verschachtelten Listen (wenn es mir auf die Reihenfolge darin ankommt und es kein gescheites Ordnungsschema gibt). Vielleicht solltest Du auch mal eine dieser Alternativen probieren.

Gruß,
Christian
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Danke CM,

habe da nur so nicht wirklich nen Plan von, könntest Du mir mal nen kurzes BSP posten? :)
thx
BlackJack

Du solltest Dich nicht ärgern das Python das macht was Du sagst. Wirklich nicht. ;-)

Code: Alles auswählen

    names = ('pulvertyp', 'pulverbasis', 'herstellerbezeichnung')
    for name in names:
        entry = Entry(self.frame_3,
                      font=('MS Sans Serif', '8', 'normal'),
                      width=30)
        entry.pack(side=TOP, anchor=Tkinter.NW, padx=5)
        setattr(self, name, entry)
Und jetzt zeig mal bitte wie man in C++ dynamisch Attribute zu einem Objekt hinzufügt.

Und gewöhn Dir Indexe in Schleifen ab, wo sie unnötig sind.
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

habe sowas mal für Buttons gebraucht... vlt hilft dir das weiter.

Code: Alles auswählen

from Tkinter import *
wdict = {'aname':1, 'bname':2, 
		'cname':3,'dname':4,
			
		}
		
class Ausgabe:
	def __init__(self, callback, *args, **kwargs ):
		self.callback=callback
		self.args=args
		self.kwargs=kwargs
		
	def __call__(self):
		print apply(self.callback, self.args, self.kwargs)
		
class Foo:
	def __init__(self, a, b):
		self.a=a
		self.b=b
	def __str__(self):
		return '%s\t\t%s' % (self.a, self.b)
		
root=Tk()
frm=Frame(root)
frm.pack(expand=YES, fill=BOTH)

frm1=Frame(root)
frm1.pack(expand=YES, fill=BOTH)

def buttons():		
	for xv, wert in wdict.items():
		b=Button(frm1, text=xv,
				width=18,height=8,borderwidth=1,
					command= Ausgabe(Foo, xv,wert) ).pack(side=LEFT,
					padx=2, pady=2, 
					expand=YES, 
				fill=BOTH
			)				
		
def main():
	buttons()

if __name__=='__main__':
	main()
	root.mainloop()

CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Weiß nicht recht BlackJack, Dein Beispiel führt dazu, daß ein Haufen "quasi-globaler" Variablen erzeugt wird (oder wie auch immer man das nennen möchte). Ich für meine Teil ziehe, wie gesagt, andere Lösungen vor. Wenn man das Problem so auffast, wie Du wäre eine Option eine "Pulverklasse" zu schreiben mit den Attributen in names und entsprechenden getter / setter Methoden (bzw. alg. get- / set-Attribut-Methode). Dann könnte man mit einer Liste von diesen Puverinstanzen gut arbeiten. Das ist zwar vom Konzept her etwas, daß in diese Thread noch nicht zur Debatte stand - könnte mir aber vorstellen, daß sunshine so etwas realisiert sehen möchte.
sunshine, möchtest Du mit verschiedenen "Pulvern" umgehen, die gleichzeitig im Programm verfügbar sind?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich würde eine Lösung über ein Dictionary machen:

Code: Alles auswählen

class Dummy:
    def __init__(self):
        #Hier werden deine dynamischen Attribute angelegt
        self.attributes = {"att1":"wert1", "att2":"wert2"

    def spam(self):
        #Zugriff in einer Schleife
        for a in self.attributes.keys():
            self.attributes[a] = "eggs"

        #oder direkt über den Attribut-Namen
        self.attributes["att1"] = "eggs"
So ähnlich wurde das ja schon vorgeschlagen, aber ich hoffe mal, dass ich das Problem so vollständig erfasst habe.
BlackJack

Also ich hatte es so verstanden das lediglich beim Erzeugen der Widgets Tipparbeit gespart werden sollte weil alle Widgets gleich aufgebaut sind. Und später wird wahrscheinlich auf einzelne Attribute mit ``self.pulvertyp`` zugegriffen. Falls man im Programm selbst nie den Namen als Bezeichner ausschreibt sondern immer nur mit Namen in Zeichenketten arbeitet, dann ist natürlich ein Dictionary oder eine Liste die bessere Wahl.

@CM: Die Attribute sind Eingabeelemente in einer GUI, es handelt sich nicht um einen Datentyp der eine Pulverart darstellt.
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Erstmal danke an alle für die tollen Antworten.

Vom Prinzip her hat BlackJack mein Problem "richtig" verstanden, es soll ne Menge Tipparbeit ersparen, denn die
names = ('pulvertyp', 'pulverbasis', 'herstellerbezeichnung')
beinhalten noch 20 weitere Elemente. Habe es auch so benutzen können und es funzt prima. MEGA-thx. :D

@ pyStyler:
So sieht es schon ganz schön prof. aus, doch für mich als python neuling doch zuviel Stoff :wink: , trotzdem thx.

@ CM:
sunshine, möchtest Du mit verschiedenen "Pulvern" umgehen, die gleichzeitig im Programm verfügbar sind?
Ja, genau sowas meinte ich. Ist evtl die optimalste Lösung, denn ich möchte in einer anderen def die eingegebenen Werte auch wieder auslesen. Denke da wäre soetwas "besser". Nur für mich nen bißchen zu hoch...

@ EyDu:
Werde mich damit nochmal mit nem bierchen zusammen auseinander setzen. :) Sieht aber auch gut aus. thx


So, wo ich nun auch schon bei meinem nächsten Prob. wäre... :oops:

Habe in einer class, eine def "pulver_anlegen" und eine def "pulver_save".
In der "pulver_anlegen" habe ich den Code von BlackJack benutzt um die entrys zu erzeugen, klappt super!!!.
Doch wie kann ich in der def "pulver_save" die Pulver wieder über ne Schleife auslesen?
Mit

Code: Alles auswählen

print self.pulvertyp.get()
funktioniert es. Muss so nur leider jedes Element einzeln ansprechen.
Wie bekomme ich das wie mit der entry-schleife realisiert?
Habe selber schon viel probiert, kam aber nix gescheites bei rum...

Code: Alles auswählen

for name in varnamen: 
       ausgabe = self.name.get()
       print ausgabe
       setattr(self, name, ausgabe)
:roll:
BlackJack

Sunshine hat geschrieben:Vom Prinzip her hat BlackJack mein Problem "richtig" verstanden, es soll ne Menge Tipparbeit ersparen, denn die
names = ('pulvertyp', 'pulverbasis', 'herstellerbezeichnung')
beinhalten noch 20 weitere Elemente. Habe es auch so benutzen können und es funzt prima. MEGA-thx. :D
Hm, ich fürchte ich hab's nicht richtig verstanden. Wenn Du nicht irgendwann mal ``self.pulvertyp`` wirklich so im Quelltext stehen haben möchtest, das heisst wenn Du immer nur indirekt auf die Werte zugreifen willst, dann ist ein Dictionary die offensichtlichere Lösung.
Habe in einer class, eine def "pulver_anlegen" und eine def "pulver_save".
In der "pulver_anlegen" habe ich den Code von BlackJack benutzt um die entrys zu erzeugen, klappt super!!!.
Doch wie kann ich in der def "pulver_save" die Pulver wieder über ne Schleife auslesen?
Mit

Code: Alles auswählen

print self.pulvertyp.get()
funktioniert es. Muss so nur leider jedes Element einzeln ansprechen.
Wie bekomme ich das wie mit der entry-schleife realisiert?
Habe selber schon viel probiert, kam aber nix gescheites bei rum...

Code: Alles auswählen

for name in varnamen: 
       ausgabe = self.name.get()
       print ausgabe
       setattr(self, name, ausgabe)
Du weisst aber *warum* das nicht funktioniert!? Was hast Du denn an Vorwissen? Fühlst Du Dich einigermassen sicher was OOP angeht?
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Nein ich weiß nicht warum das funktioniert.
Natürlich fühle ich mich in OOP nicht sicher, sonst würde ich damit auch sicherlich nicht so rumkaspern! :wink:
Als vorwissen hatte ich in der FH nur C grundkurse, aber nicht mit OOP.

Kannste mir denn trotzdem verraten wie das funzen kann? :)
BlackJack

Dann solltest Du unbedingt ein Tutorial zu OOP durcharbeiten.

`name` ist ein Name in der Methode und diesen Namen bindest Du an Zeichenketten.

In der Schleife greifst Du auf `self.name` zu, das hat aber nichts mit `name` zu tun! Der Name `self` ist an das Objekt gebunden, auf dem die Methode aufgerufen wurde und mit `self.name` versuchst Du auf ein Attribut mit dem Namen `name` zuzugreifen. Das gibt's aber nicht, also haut's Dir einen `AttributeError` um die Ohren.

Die Lösung ist doch eher, dass Du in der einen Methode die Zeichenketten mit den "Variablennamen" zusammen mit den erzeugten `Entry`-Objekten in eine Liste oder ein Dictionary steckst und das an das Objekt bindest, damit Du in der `save`-Methode dann wieder an alle Objekte heran kommst.

Code: Alles auswählen

def create(self):
    self.attributes = dict()
    for name in ('pulvertyp', 'pulverbasis', 'herstellerbezeichnung'):
        entry = Entry(self.frame_3,
                      font=('MS Sans Serif', '8', 'normal'),
                      width=30)
        entry.pack(side=TOP, anchor=Tkinter.NW, padx=5)
        self.attributes[name] = entry

def save(self):
    for name, entry in self.attributes.iteritems():
        print '%s = %s' % (name, entry.get())
Sunshine
User
Beiträge: 9
Registriert: Dienstag 21. November 2006, 19:14

Dann solltest Du unbedingt ein Tutorial zu OOP durcharbeiten.
Da magste wohl recht haben, scheint am sinnvolslten zu sein! :D


Habe es so wie von dir gepostet eingefügt und wie solls auch anders sein, es funktioniert prima. Danke BlackJack!
Antworten