Klassenweite Variablen

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.
freq.9

Wie bekomme ich Klassenweiter Variablen hin? Also ich will in jeder Funktion eine bestimmte Variable so nutzen können. In PHP ists ja so, dass ich das mit $this mache aber in Python bin ich soweit noch nicht, dass ich das weiss und in der Doc finde ich nun auch nichts passendes.

Wie ich es meine:

Code: Alles auswählen

class Foo:
    def __init__(self):
        moep = "Hallo"

    def __del__(self):
        print moep
Wenn ich das so machen würde, bekomme ich folgende Meldung:
Exception exceptions.NameError: "global name 'moep' is not defined" in <bound me
thod Foo.__del__ of <__main__.Foo instance at 0x009C6800>> ignored
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

Die Klassenkonzepte von PHP und Python ähneln sich durchaus. In PHP (und C++) gibt es "this", in Python "self". Das ist zwar systaktisch und semantisch ein bißchen was anderes - und deshalb würde ich Dir schon noch empfehlen die Pythondoku in dem Punkt etwas genauer anzuschauen -, aber prinzipiell geht das so:

Code: Alles auswählen

class Foo:
    def __init__(self):
        self.bar = 'Hallo'
    def __repr__(self):
        return self.bar

x = Foo()
print x
... sollte brav "Hallo" sagen, denn mit "self" kannst Du innerhalb einer Klasse auf die klasseneigenen Parameter zugreifen. Von globalen Variablen würde ich hierbei aber nicht gebrauch machen.

Gruß,
Christian
freq.9

Jau cool danke funktioniert. Hatte ich doch eigentlich am Anfang so gemacht, oder nicht!? Naja nun gehts ;) Danke.

Hatte schon auf ner anderen Seite im Netz was über "global" gelesen aber als ich das getestet hab, habe ich immer "None" statt meinen Wert ausgegeben bekommen.
freq.9

Achso ne Frage hätt ich dann doch noch dazu:

Code: Alles auswählen

 class Foo:
    def __init__(self):
        self.moep = "Hallo"

    def __del__(self):
        self.moep = self.moep, " Welt"
Das geht nicht. Wie wäre das denn richtig?
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Nein, Du hattest am Anfang auf "moep" zugegriffen, das aber in __del__ nicht bekannt war.

Zur letzten Frage: Was bitte ist "Welt"?

Aber die Beantwortung überlasse ich jetzt anderen.

Gute Nacht,
Christian

PS Wir mal einen Blick hier hinein.
freq.9

CM hat geschrieben:Nein, Du hattest am Anfang auf "moep" zugegriffen, das aber in __del__ nicht bekannt war.

Zur letzten Frage: Was bitte ist "Welt"?

Aber die Beantwortung überlasse ich jetzt anderen.

Gute Nacht,
Christian

PS Wir mal einen Blick hier hinein.
Ich möchte "Welt" an den String in moep anhängen. In PHP sähe das wie folgt aus:

Code: Alles auswählen

$moep = "Hallo";
$moep = $moep . " Welt";

print $moep; // würde "Hallo Welt" ausgeben
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

hi

Dann geh doch in der Doku nachlesen, wie man Strings zusammenkettet.

Allgemein ist es eine gute Idee das Tutorial mal zu durchlesen.

Gruss
freq.9
User
Beiträge: 4
Registriert: Donnerstag 12. Mai 2005, 06:13
Wohnort: BRD, NRW, Beckum
Kontaktdaten:

rayo hat geschrieben:hi

Dann geh doch in der Doku nachlesen, wie man Strings zusammenkettet.

Allgemein ist es eine gute Idee das Tutorial mal zu durchlesen.

Gruss
So nun hab ich mich mal registriert.

Also scheinbar liegt mein Fehler nicht bei der Verkettung von zwei "Strings" sondern, dass ich einmal ein "Tuple" und ein "String" zusammenfügen will und das scheinbar nicht mal eben so geht.

Also hier mal mein Script:

Code: Alles auswählen

class RSS:
	def __init__(self):
		self.node_count 	= 0
		self.nope_opened	= -1
		self.required		= [-1, -1, -1]
		self.xml			= "<?xml version="1.0"?>\n <rss version="2.0">\n  <channel>\n"
	
	def __del__(self):
		""" In die *.xml Datei schreiben """
		self.xml			+= "  </channel>\n </rss>\n"
		print self.xml
		
	def addNode(self, obj):
		self.node_opened 	= 1
		self.node_count		+= 1
		
		if self.node_count == 1:
			self.xml 		+= "\n  <!-- Items -->\n", obj.get()
		else:
			self.xml		+= obj.get()
			
	def addLanguage(self):
		return ElementWithValue('language')

class ElementWithValue:
	def __init__(self, element, sub = -1):
		if sub != -1:
			self.xml		= "   <", element
		else:
			self.xml		= "  <", element
	
	def addAttribute(self, key, value):
		self.xml			+= " ", key, "="", value, """
	
	def get(self):
		return self.xml, " />\n"
		
x = RSS()
x2 = x.addLanguage()
x2.addAttribute("foo", "bar")
x.addNode(x2)
Und wenn ich das so ausführe wie es jetzt ist, dann bekomme ich dies ausgegeben:
Traceback (most recent call last):
File "C:\Server\Apache2\Python\Lib\rss\rss.py", line 56, in ?
x.addNode(x2)
File "C:\Server\Apache2\Python\Lib\rss\rss.py", line 33, in addNode
self.xml += "\n <!-- Items -->\n", obj.get()
TypeError: cannot concatenate 'str' and 'tuple' objects
<?xml version="1.0"?>
<rss version="2.0">
<channel>
</channel>
</rss>
Btw: Wie gesagt sind das noch die anfänge. Ich versuche lediglich eine Bibliothek aus PHP in Python zu schreiben. So hab ich immer einen kleinen vergleich.

Und die Doku hab ich nun schon seit 2 Tagen durchgehen offen. Ich suche da wohl schon nur leider bin ich nicht so unbedingt der Profi in der englischen Sprache und von daher finde ich so manch Sachen nicht mal eben so. Sorry :!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi

Du machst gleich mehrere Denkfehler:
1.) Wozu brauchst Du __del__? Denkst Du an einen Destruktor? Brauchst Du (hier) gar nicht. Sowie Python keine Referenz mehr auf ein Objekt findet, wird der Speicher automatisch freigegeben. Wenn Du zusätzlich __del__ definierst, dann wird diese Funktion ausgeführt bevor die Referenz freigegeben wird. Es ist quasi ein finales Statement: "Wenn Du, mein Pythonskript, schon aufräumen willst - dann mache vorher noch dieses, das und jenes!"
2.) Was Du hier willst, so scheint es mir, ist in eine Datei schreiben? Aber Du hast gar keinen Stream geöffnet!
3.) Frage dich mal was obj ist. Dazu schau mal was passiert wenn Du obj.get() auszudrucken versuchst. Du wirst eben ein Objekt sehen (hier x2). Aber da Du Python nicht erzählt hast, was es damit machen soll, z. B. den String eines Element rausgeben, hat es diese Info nicht und versucht das ganze x2-Objekt mit x zu verketten - das geht natürlich nicht. Was Du - vielleicht möchtest - ist self.xml mit obj.xml zu verketten. Das allerdings sollte funktionieren.

Gruß,
Christian

PS Schau mal weiter unten in das Forum zu den Tutorials - dort gibt es auch eine Reihe von Links auf deutschsprachige Seiten.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Code: Alles auswählen

self.xml			= "<?xml version=\"1.0\"?>\n <rss version=\"2.0\">\n  <channel>\n"
Das geht einfacher:

Code: Alles auswählen

self.xml			= '<?xml version="1.0"?>\n <rss version="2.0">\n  <channel>\n'

Code: Alles auswählen

self.xml 		+= "\n  <!-- Items -->\n", obj.get()
String zu erweitern geht mit "+" nicht mit ","

Code: Alles auswählen

self.xml 		+= "\n  <!-- Items -->\n" + obj.get()

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
freq.9
User
Beiträge: 4
Registriert: Donnerstag 12. Mai 2005, 06:13
Wohnort: BRD, NRW, Beckum
Kontaktdaten:

Zu den Denkfehlern:
1) Das mit dem Destruktor, da hattest du Recht. Ich hätte nun mal gedacht, dass es ein Destruktor ist. Wobei in der Doc folgendes steht:
3.3.1 Basic customization hat geschrieben:__del__( self)
Called when the instance is about to be destroyed. This is also called a destructor.
2) Ich bin grade dabei mich mit Python zu beschäftigen und werde mich erst mit dem "in Dateien schreiben" befassen, sobald ich das XML Konstrukt per print richtig ausgeben kann. Vorher brauche ich ja auch noch nicht in eine Datei zu schreiben.

3) Aber wieso gibt denn obj.get() das Objekt wieder? obj ist doch die Instanz der class ElementWithValue. Und in Funktion get() in ElementWithValue soll doch self.xml zurückgegeben werden. Geht doch in PHP etc. auch so!?

--> Tutorials: Jau werd ich mir mal angucken. Hab mir bisher nur dieses eine Forum angesehen.

@ jens:
Hmmm. Bei mir kam da einmal ne Fehlermeldung und da dachte ich, dass das nicht geht. Muss wohl an was anderem gelegen haben, wenn es doch geht.
erweitern mit "+", aber für was ist dann ","?
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hi,

vielleicht solltest Du Dir doch erst mal das Tutorial durchlesen, bevor Du in Details einsteigst?

Zu __del__: Lies Dir mal den Rest dazu durch.
Zu Dateien: Das ist in Python so einfach (verglichen mit C oder PHP), das kannst Du im Tutorial mal eben so mitnehmen und verstehen.
Zu Deiner get()-Methode: Diese Methode ist eine von ElementWithValue und nicht von RSS! Und x2 ist eine Instanz von RSS und RSS kennt get() nicht. Auch PHP kennt diesen Unterschied ;-).

Zu + vs. ,: Das steht auch im Tutorial. Was Du an manchen Stellen machst ist tuple von (Rückgabe-)Werten erzeugen und diese dann noch verketten. Das kann man machen, aber ich glaube, das ist nicht was Du willst.

Zu dem "Englisch-Problem": Wie hast Du denn PHP gelernt? Also, wenn alle Stricke reißen, müßtest Du halt in ein deutschsprachiges Buch investieren.

Gruß,
Christian

PS Es gibt auch das eine oder andere xml-Modul für Python. Vielleicht könntest Du das nutzen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Und bitte, bitte, bitte tu zwischen die Zuweisung (zB: self.xml = '<?xml version="1.0"?>\n <rss version="2.0">\n <channel>\n') nur ein Leerzeichen davor und danach. Das hat zwar keine Bedeutung für Python, wohl aber für die Programmierer die deinen Code lesen. und das ist unpraktisch und verwirrt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

CM hat geschrieben:Zu dem "Englisch-Problem": Wie hast Du denn PHP gelernt? Also, wenn alle Stricke reißen, müßtest Du halt in ein deutschsprachiges Buch investieren.
Als Einstieg ist allerdings schon einiges da s. http://www.python-forum.de/viewtopic.php?p=13877#13877

Wobei natürlich ein umfassendes Buch/Seite wir z.B. selfPHP schon nicht schlecht wäre :cry: An der original Doku stört mich am meißten, das es einfach zu wenige Beispiele enthält...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

jens hat geschrieben: An der original Doku stört mich am meißten, das es einfach zu wenige Beispiele enthält.
Dafür gibts ja hier die Codesnippets und das Showcase :)
BlackJack

Jetzt hat ihm immer noch niemand seine Ausgangsfrage beantwortet. Klassenweite Variablen bekommt man, in dem man sie auf der "Ebene" der Klasse definiert und über den Klassennamen referenziert:

Code: Alles auswählen

class Spam:
    counter = 0
    def __init__(self):
        Spam.counter += 1
        print 'Es wurden schon %d Spam-Instanzen erzeugt' % Spam.counter
Aber er wollte ja offensichtlich Instanzvariablen haben. :wink:

Ein Programm aus einer anderen Sprache in eine neue mehr oder weniger 1:1 übersetzen zu wollen produziert übrigens in vielen Fällen ziemlich hässlichen Quelltext. Wenn die Sprachen alle gleich funktionieren würden und die gleichen Idiome und Muster verfolgen würden, dann bräuchte man ja gar nicht erst verschiedene Sprachen.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Der Punkt geht an Dich - trotz Haarspalterei :D .
Gast

hallo zusammen,

na ich weiss nicht, ob das beispiel von BlackJack gut ist, gut in dem sinne es nachzuahmen und darauf aufzubauen. klassenvariablen würde ich im konstruktor so nicht verändern.
besonders wenn es später um vererbung geht, kann das ungewünschte effekte bringen.

Bsp:

BlackJack's Variante, dann meine:

Code: Alles auswählen

>>> class Spam:
	counter=0
	def __init__(self):
		Spam.counter += 1
		print 'Es wurden schon %d Spam-Instanzen erzeugt' % Spam.counter

		
>>> spam=Spam()
Es wurden schon 1 Spam-Instanzen erzeugt
>>> Spam.counter
1
>>> spam.counter
1
>>> class Spam:
	counter=0
	def __init__(self):
		self.counter += 1
		print 'Es wurden schon %d Spam-Instanzen erzeugt' % self.counter

		
>>> spam=Spam()
Es wurden schon 1 Spam-Instanzen erzeugt
>>> Spam.counter
0
>>> spam.counter
1
>>> 

will sicher nicht klugscheissen, sondern habe mir nur mal meine gedanken gemacht.


lg,

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

Aber das Funktioniert doch so nicht:

Code: Alles auswählen

>>> Spam()
Es wurden schon 1 Spam-Instanzen erzeugt
>>> Spam()
Es wurden schon 1 Spam-Instanzen erzeugt
Es sollte aber zwei zeigen, insofern würde ich BlackJacks Variante nehmen, wenn ich will dass alle Klasseninstanzen die Variable sich teilen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Gast

hi leonidas,
Aber das Funktioniert doch so nicht:
stimmt schon was du sagt, ich hatte an ein bsp. von mir gedacht, das ich programmiert habe und dachte, dass ich da in teufelsküche gekommen wäre,......naja dann wurde mir wieder klar, dass python ja soviele möglichkeiten bietet etwas anzugehen, dass ich nur einiges ändern müsste und es würde auch wieder laufen,

wahrscheinlich war es für mich einfach etwas seltsam zu sehen, dass eine klassenvariable im konstruktor der eine instanz erstellt in dieser weise verändert wird.

lg

rolgal
Antworten