Seite 1 von 1

Auf Attribut einer importierenden Klasse zugreifen (gelöst)

Verfasst: Freitag 8. August 2008, 11:31
von erebus
Hallo erstmal, ich mache hier mal meinen ersten Beitrag (leider in Form einer Frage).

Hintergrund (muss man nicht unbedingt lesen):

Ich schreibe gerade einen Fileserver (für mich persönlich), den ich schonmal so ähnlich mit PHP realisiert habe. Nun hat das alte PHP-Ding doch einige Verbesserungen nötig und da ich im Moment wenig Lust auf PHP habe, dachte ich, das ließe sich doch prima mit Python machen. Nach kurzer Einarbeitung in CherryPy (für die, die es nicht kennen, es ist ein Python-HTTP-Framework) konnte ich also Loslegen und habe auch schon gute fortschritte gemacht (Login-Funktionen, Benutzerverwaltung, Download von Dateien funktionieren schon). Aber ich stoße gerade als Neuling auf ein Problem, was eventuell zu lösen ist. Vielleicht habe ich dem Thema (ich bin autodidakt) ein bißchen zu wenig Aufmerksamkeit geschenkt.

Problemstellung:

Ich muss von einer importierten Klasse auf eine Klassenattribut der importierenden Klasse zugreifen. In meinem speziellen Fall geht es um Daten, die während eine Uploads (zum Server) über den laufenden Transfer gespeichert werden sollen (für einen Fortschirttsanzeige), der Prozess geht von einer importierten Klasse aus, soll die Daten aber in der importierenden Klasse ablegen, weil eine andere Funktion (diese ist eine Funktion der importierenden Klasse) während des Uploads diese Daten abfragen soll.

In der Grafik (siehe unten) hoffe ich zu verdeutlichen, was ich meine. Die Datei klasse1.py ist deshalb Teil eines Moduls, weil der eigentliche Code, der für ein Beispiel zu umfangreich ist, auch aus einem Modul importiert. Ich stelle das hier mal in einem Minimalbeispiel dar. Wie müsste ich also das Attribut "a" referenzieren um Zugriff darauf zu haben?

Bild

LG
erebus

Verfasst: Freitag 8. August 2008, 12:02
von BlackJack
"Importierende Klassen" macht nicht viel Sinn. Klassen importieren nichts, das macht man mit der ``import``-Anweisung, und die kann zwar so ziemlich überall verwendet werden, wo man Anweisungen verwenden kann, aber das ist in der Regel am Anfang von Modulen.

Also ist die Frage was Du mit "importierender Klasse" eigentlich meinst?

Für Fortschrittsinformation bietet es sich an, der Funktion die die Arbeit verrichtet, eine Rückruffunktion mit zu geben, die sie in gewissen Abständen dann mit entsprechenden Fortschrittsdaten auf ruft.

Verfasst: Freitag 8. August 2008, 12:07
von audax
Böse. Das geht mit ein wenig Gefrickel zu Lösen, ist aber nicht schön.

http://effbot.org/zone/import-confusion.htm
Dort unter "recursive imports" ist dein Problem beschrieben.

Zur Kommunikation zwischen Thread könntest du z.B. Queues machen, aber lieber nicht mit Klassenattributen.

Verfasst: Freitag 8. August 2008, 12:16
von erebus
@audax, danke, aber hat nicht geholfen.

ich habe jetzt:

klassentest.py:

Code: Alles auswählen

import klasse1
class Root():
	
	a = 500
	def __init__(self):
		x = klasse1.Klasse1()
		x.eineFunktion()
		print u'Nach der Veränderung eineFunktion() - klassentest.Root:', Root.a

if __name__ == '__main__':
	Root()
und

klasse1.py:

Code: Alles auswählen

class Klasse1():
	test = 100

	def eineFunktion(self):
		import klassentest
		klassentest.Root.a = Klasse1.test
		print u'Nach der Veränderung durch eineFunktion() - klasse1.Klasse1:', klassentest.Root.a
Ausgabe ist:

Code: Alles auswählen

Nach der Veränderung durch eineFunktion() - klasse1.Klasse1: 100
Nach der Veränderung eineFunktion() - klassentest.Root: 500
Anscheinend sind die Klassen "klassentest.Root" (von Klasse1 aus) und "Root" (von Klasse Root aus bzw. nicht aus klasse1.py aus) verschieden. Ich habe also eine lokale Version von Root in Klasse1. Das will ich aber nicht, ich möchte auf die Klasse Root zugreifen können, von der aus klasse1 importiert wird. :-( Ich will das die Ausgabe so aussieht:

Code: Alles auswählen

Nach der Veränderung durch eineFunktion() - klasse1.Klasse1: 100
Nach der Veränderung eineFunktion() - klassentest.Root: 100
EDIT (Gelöst) : :twisted:

Hab anscheinend eine Lösung gefunden. Vielleicht geht es noch eleganter:

klassentest.py:

Code: Alles auswählen

import klasse1
class Root():
	
	a = 500
	def __init__(self):
		x = klasse1.Klasse1()
		x.eineFunktion(Root)
		print u'Nach der Veränderung eineFunktion() - klassentest.Root:', Root.a

if __name__ == '__main__':
	Root()
klasse1.py:

Code: Alles auswählen

class Klasse1():
	test = 100

	def eineFunktion(self,xclass):
		import klassentest
		xclass.a = Klasse1.test
		print u'Nach der Veränderung durch eineFunktion() - klasse1.Klasse1:', xclass.a
Mann muss also eine Referenz auf die "Ober"-Klasse (nicht im Sinne von Vererbung) mitgeben, oder gibt es noch eine möglichkeit um an eine Referenz auf Root zu kommen?

Verfasst: Montag 11. August 2008, 21:50
von bastian.weber
Ich glaube richtig professionell würde man es mit Threads machen, aber da kenne ich mich auch nicht aus.

Jedenfalls bin ich der Meinung, dass in Deinem letzten (also funktionierenden) Codebeispiel der Import von klassentest in eineFunktion() unnötig ist.

Vielleicht solltest Du auch darüber nachdenken, in der Klasse Root ein Kommunikationsobjekt anzulegen, welches Du dann rumreichen kannst. Das finde ich besser, als gleich die ganze Klasse zu übergeben nur weil dort ein Wert gesetzt werden soll. das widerspricht imo dem Paradigma, dass ein Objekt nur auf die Daten und Funktionalität Zugriff haben sollte mit denen es sinnvoll Arbeiten kann.