Hallo.
Folgender Code (Auch im Anhang als Klassentest.py enthalten):
1
# -*- coding: utf-8 -*-
2
import tkinter
3
from tkinter.filedialog import *
4
5
class Klassendef:
6
def __init__(self):
7
self.a = "Var a"
8
self.b = "Var b"
9
print ("initialisierung")
10
print (self.a)
11
print (self.b)
12
print ("initialisierung ende")
13
14
def funktion1(self):
15
self.a = self.a + "+a"
16
17
def funktion2(self):
18
self.b = self.b + "+b"
19
20
print ("Vor Initialisierung")
21
22
class ersteKlasse (Klassendef):
23
pass
24
25
class zweiteKlasse (Klassendef):
26
pass
27
print ("initilasierung erste Klasse")
28
ersteKlasse.__init__(ersteKlasse)
29
30
print ("initilasierung zweite Klasse")
31
zweiteKlasse.__init__(zweiteKlasse)
32
33
34
35
print ("erste Klasse a = " + ersteKlasse.a)
36
ersteKlasse.funktion1(ersteKlasse)
37
print ("jetzt erste Klasse a = " + ersteKlasse.a)
38
39
print ("zweite Klasse a = " + zweiteKlasse.a)
40
zweiteKlasse.funktion1(zweiteKlasse)
41
print ("jetzt zweite Klasse a = " + zweiteKlasse.a)
42
43
ersteKlasse.a = "test1"
44
zweiteKlasse.a ="test2"
45
46
print (ersteKlasse.a)
47
print (zweiteKlasse.a)
48
49
ersteKlasse.funktion1(ersteKlasse)
50
print ("jetzt erste Klasse a = " + ersteKlasse.a)
funktioniert so (erst) einmal.
Die Idee ist, zwei Objekte, "ersteKlasse" und "zweiteKlasse" als
abgeleitete Klassen aus "Klassendef" zu erstellen, und dann ersteinmal
mit den gleichen Variableninhalten zu füllen.
dies geschieht in
1
class ersteKlasse (Klassendef):
2
pass
3
class zweiteKlasse (Klassendef):
4
pass
5
6
print ("initilasierung erste Klasse")
7
ersteKlasse.__init__(ersteKlasse)
8
9
print ("initilasierung zweite Klasse")
10
zweiteKlasse.__init__(zweiteKlasse)
Was ich irgendwie "unelegant" finde, ist das "pass". NOPs sind mir zwar
aus Assembler wohlbekannt, aber in einer Hochsprache oder gar
Skriptsprache (vermutlich) eher selten. Lasse ich die "pass" aber weg,
bekomme ich die Fehlermeldung, das der Interpreter hier eine Einrückung
erwartet, was eigentlich auch impliziert, das er zu class .....
passenden/folgenden code erwartet.
Nun gut, eigentlich könnte ich ja die anschliessenden Initialisierungen
statt der "pass" dort einfügen, dann hätte ich die den passenden Code
dort, das "pass" wäre weg, und mein Listing etwas eleganter.
Der entsprechende Abschnitt lautet dann:
1
class ersteKlasse (Klassendef):
2
print ("initilasierung erste Klasse")
3
ersteKlasse.__init__(ersteKlasse)
4
5
class zweiteKlasse (Klassendef):
6
print ("initilasierung zweite Klasse")
7
zweiteKlasse.__init__(zweiteKlasse)
Leider aber ist das FALSCH, weil ich nun die Fehlermeldung
1
>>>
2
Vor Initialisierung
3
initilasierung erste Klasse
4
Traceback (most recent call last):
5
File "/home/wiebus/python/Klassentest_2.py", line 22, in <module>
6
class ersteKlasse (Klassendef):
7
File "/home/wiebus/python/Klassentest_2.py", line 24, in ersteKlasse
8
ersteKlasse.__init__(ersteKlasse)
9
NameError: name 'ersteKlasse' is not defined
10
>>>
bekomme, was heisst, die erhoffte Initialisierung hat überhaupt nicht
stattgefunden, weil "ersteKlasse", welche ich durch "class
ersteKlasse(Klassendef) definiert wähnte, überhaupt noch nicht
existiert?????
Aber in der ursprünglichen Version mit "pass" existiert die Klasse nach
verlassen der Klassendefinition?
Meine Intuition sagt mir jetzt, das ich einen dicken Denkfehler mache,
aber wenn ja, wo und warum und wenn nein, wie geht es besser?
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
PS: BS ist Debian squeeze.
Hallo Norbert.
> Habe unter Squeeze zwar nur Python 2.6.something installiert, aber...>> Soll es eventuell so wie im Anhang funktionieren?
Nach Umbau auf Python 3 funktioniert es genauso wie die Ursprüngliche
Version, und natürlich auch das angehängte "show".
Alledings ist mir jetzt noch weniger klar, was da jetzt passiert.
Das "pass" ist nicht weg, und die Initialisierung erfolgt jetzt durch
das Zuweisen "ek = ersteKlasse()" und "zk = zweiteKlasse()"????
Mir fehlt dort wohl noch etwas Theorie, mein Lehrbuch scheint in dem
Punkte etwas mager zu sein. Das Lehrbuch macht es so wie Du, erklärt
aber auch nicht, warum.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
So, habe mal python 3 in wheezy installiert und etwas vorbereitet;-)
Vielleicht wird der Ablauf so klarer:
1
#!/usr/bin/env python3
2
3
print('--->1')
4
5
classBasisKlasse(object):
6
print('--->2')
7
instzaehler=0
8
instzaehler2=0
9
10
def__init__(self):
11
print('--->5:%d'%self.instzaehler)
12
print('--->5:%d'%BasisKlasse.instzaehler2)
13
self.instzaehler+=1
14
BasisKlasse.instzaehler2+=1
15
16
defdummy(self):
17
print('dummy')
18
19
print('--->3')
20
21
classB(BasisKlasse):
22
pass
23
24
classC(BasisKlasse):
25
pass
26
27
print('--->4a')
28
29
BasisKlasse.dummy(None)
30
31
print('--->4b')
32
33
Instanz_basis=BasisKlasse()
34
35
print('--->6')
36
37
Instanz_b=B()
38
39
print('--->7')
40
41
Instanz_c=C()
42
43
print('--->8')
44
45
#--->1
46
#--->2
47
#--->3
48
#--->4a
49
#dummy
50
#--->4b
51
#--->5:0
52
#--->5:0
53
#--->6
54
#--->5:0
55
#--->5:1
56
#--->7
57
#--->5:0
58
#--->5:2
59
#--->8
_init_ wird erst aufgerufen, wenn eine Instanz einer Klasse gebildet
wird.
Man kann auch schön sehen, das instzaehler in jeder Instanz einen
eigenen lokalen Wert hat.
Die Variable instzaehler2 'gehört' allen Instanzen
Bernd Wiebus schrieb:> Was ich irgendwie "unelegant" finde, ist das "pass". NOPs sind mir zwar> aus Assembler wohlbekannt, aber in einer Hochsprache oder gar> Skriptsprache (vermutlich) eher selten.
1
// warte auf gesetztes Flag
2
while(flag==0)
3
;/* <- Da ist das "nop" */
> Lasse ich die "pass" aber weg, bekomme ich die Fehlermeldung, das der> Interpreter hier eine Einrückung erwartet, was eigentlich auch> impliziert, das er zu class ..... passenden/folgenden code erwartet.
Vergleiche es mal mit C++. Wenn ich da schreibe
1
classIrgendwas
2
{
dann erwartet der Compiler, daß irgendwo auch mal ein
1
};
dazu kommt, also der Codeblock wieder geschlossen wird. Python hat aber
keine Klammern für den Block, sondern nur die Einrückung. Also muß da
nach dem Kopf der Klassendefinition (oder überall, wo ein Doppelpunkt am
Zeilenende steht) was eingerücktes stehen, damit der Codeblock
vollständig ist. Da du aber in diesem Fall nichts zum einrücken hast,
brauchst du irgendwas, das du hinschreiben kannst, das aber keinen
Effekt hat. Und dafür ist dann das pass da.
Hallo Norbert, hallo Rolf.
Vielen Dank für Eure Antworten.
> So, habe mal python 3 in wheezy installiert und etwas vorbereitet;-)> Vielleicht wird der Ablauf so klarer:
Danke, ich werde mit dem Code morgen mal was rumspielen. Er scheint mir
ein paar zusätzliche Fragen zu klären...z.B. was hinterher die
Unterschiede in den einzelnen Klassen, die unterschiedlich erzeugt
wurden, sind.
Zu:
1
def __init__(self):
2
print('--->5:%d' % self.instzaehler)
3
print('--->5:%d' % BasisKlasse.instzaehler2)
4
self.instzaehler += 1
5
BasisKlasse.instzaehler2 += 1
> Man kann auch schön sehen, das instzaehler in jeder Instanz einen> eigenen lokalen Wert hat.> Die Variable instzaehler2 'gehört' allen Instanzen
Uuups.....das erklärt mir auch eine andere Merkwürdigkeit. ;O)
> init wird erst aufgerufen, wenn eine Instanz einer Klasse gebildet> wird.
Ah, aber _init_ wird dann automatisch aufgerufen, wenn ich z.b. mit
"Instanz_b = B()" eine Instanz erzeuge. Ich muss NICHT extra
"Instanz_b.__init__()" aufrufen.....das war mir auch nicht klar.
>> Was ich irgendwie "unelegant" finde, ist das "pass". NOPs sind mir zwar>> aus Assembler wohlbekannt, aber in einer Hochsprache oder gar>> Skriptsprache (vermutlich) eher selten.> Vergleiche es mal mit C++. Wenn ich da schreibe
Ok,ok C bzw. C++ kann ich zwar noch weniger..... ;O)
> dazu kommt, also der Codeblock wieder geschlossen wird. Python hat aber> keine Klammern für den Block, sondern nur die Einrückung. Also muß da> nach dem Kopf der Klassendefinition (oder überall, wo ein Doppelpunkt am> Zeilenende steht) was eingerücktes stehen, damit der Codeblock> vollständig ist. Da du aber in diesem Fall nichts zum einrücken hast,> brauchst du irgendwas, das du hinschreiben kannst, das aber keinen> Effekt hat. Und dafür ist dann das pass da.
Ok. DAS leuchtet mir ein und beantwortet einen Teil meiner Frage.
Also sind "NOPs" in einer Hochsprache durchaus noch vorhanden, auch wenn
man sie als solche kaum erkennt. ;O)
Irgendwie bin ich davon ausgegangen, das der Interpreter erkennt, daß
auf das class keine Einrückung folgt, sondern ein neues class in
gleicher Ebene, und eine Heuristik existiert, die erkennt, wie es
gemeint ist....
möglicherweise würde das aber auch oft zu missverständlichen Situationen
führen bzw. Fehler würden nicht erkannt,.....mit Compiler- oder
Interpreterbau habe ich mich auch noch nie auseinandergesetzt.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
>Also sind "NOPs" in einer Hochsprache durchaus noch vorhanden, auch wenn>man sie als solche kaum erkennt. ;O)>Irgendwie bin ich davon ausgegangen, das der Interpreter erkennt, daß>auf das class keine Einrückung folgt,
Mit "NOPs" hat das wenig zu tun -- oder würdest Du die Semikolons, mit
denen in C das Ende einer Anweisung gekennzeichnet wird, als NOP
bezeichnen?
Und das 'pass' sollte ja nur vorübergehend notwendig sein:
http://openbook.galileocomputing.de/python/python_kapitel_06_003.htm
Ruby ist in dieser Hinsicht wohl etwas smarter, aber natürlich auch
nicht perfekt. Etwa dass Instance-Variablen stets mit @ beginnen müssen,
das kann anfangs schon befremdlich wirken...
Hallo Stefan.
>> Also sind "NOPs" in einer Hochsprache durchaus noch vorhanden, auch wenn>> man sie als solche kaum erkennt. ;O)> Mit "NOPs" hat das wenig zu tun -- oder würdest Du die Semikolons, mit> denen in C das Ende einer Anweisung gekennzeichnet wird, als NOP> bezeichnen?>
Nicht? Ok, von c hab ich keine Ahnung. Da hab ich mich wohl geirrt.
>>Irgendwie bin ich davon ausgegangen, das der Interpreter erkennt, daß>>auf das class keine Einrückung folgt,> Und das 'pass' sollte ja nur vorübergehend notwendig sein:
Ok. ;O)
> Ruby ist in dieser Hinsicht wohl etwas smarter, aber natürlich auch> nicht perfekt. Etwa dass Instance-Variablen stets mit @ beginnen müssen,> das kann anfangs schon befremdlich wirken...
Hauptsache es ist eindeutig.....
Das mit den Einrückungen bei Python ist auch so eine Sache. Die Tiefe
lässt sich über mehrere Bildschirmseiten hinweg nicht immer gut
verfolgen.
Aber vieleicht ist das ja auch ein Wink mit dem Zaunpfahl, die
Unterprogramme kürzer zu halten.
Mittlerweile habe ich mich auch daran gewöhnt.
Im Anhang befindet sich noch "KlassenDemo_09Jul2012.py". Da habe ich ein
kleines Demo Programm geschrieben, und mit einfachen Fällen von Klassen
herumgeübt und um ein Beispiel zu haben.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Bernd Wiebus schrieb:> Das mit den Einrückungen bei Python ist auch so eine Sache. Die Tiefe> lässt sich über mehrere Bildschirmseiten hinweg nicht immer gut> verfolgen.> Aber vieleicht ist das ja auch ein Wink mit dem Zaunpfahl, die> Unterprogramme kürzer zu halten.> Mittlerweile habe ich mich auch daran gewöhnt.
Falls Du mit GNU/Linux arbeiten solltest, kann ich Dir 'kate' sehr
empfehlen. Dort kann man neben vielen anderen Dingen wie
Syntax-Highlighting auch 'indentation lines' einstellen.
Sieht dann wie im Anhang aus (als Beispiel bash).
Bernd Wiebus schrieb:> Irgendwie bin ich davon ausgegangen, das der Interpreter erkennt, daß> auf das class keine Einrückung folgt, sondern ein neues class in> gleicher Ebene, und eine Heuristik existiert, die erkennt, wie es> gemeint ist....
Sowas würde die Sprachregeln verkomplizieren, was man bei den meisten
Sprachen versucht, zu vermeiden. Gerade eine Heuristik macht das ganze
nur unnötig kompliziert.
Bernd Wiebus schrieb:>> Mit "NOPs" hat das wenig zu tun -- oder würdest Du die Semikolons, mit>> denen in C das Ende einer Anweisung gekennzeichnet wird, als NOP>> bezeichnen?>>> Nicht? Ok, von c hab ich keine Ahnung. Da hab ich mich wohl geirrt.
Wie man's nimmt. Ein Semikolon für sich alleine könnte man durchaus als
eine Art "NOP" ansehen. Aber ein NOP in Assembler ist ja eine echte
Instruktion, die tatsächlich auf dem Prozessor ausgeführt wird und die
dementsprechend auch etwas Speicher und Rechenzeit verbraucht. Das
Semikolon in C dagegen taucht im erzeugten Maschinencode natürlich nicht
mehr auf. Es ist ein rein sprachliches Konzept.
Bei Python und dem PASS ist es wieder etwas anders, da es als
Interpreter die Anweisungen ja on the fly während der Ausführung
durchgeht und interpretiert. Ausgeführt wird hier auch nichts, aber der
Parser muß das PASS natürlich auswerten.
Hallo Norbert.
> Falls Du mit GNU/Linux arbeiten solltest, kann ich Dir 'kate' sehr> empfehlen. Dort kann man neben vielen anderen Dingen wie> Syntax-Highlighting auch 'indentation lines' einstellen.> Sieht dann wie im Anhang aus (als Beispiel bash).
Danke für den Tipp! Das ist für Python schon hilfrreich. Eine
Einrückungsebenen übersehen, und man schreibt ein ganz anderes Programm
und wundert sich....;O)
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Hallo Rolf.
> Das Semikolon in C dagegen taucht im erzeugten Maschinencode natürlich >nicht
mehr auf. Es ist ein rein sprachliches Konzept.
Ok, soweit habe ich das jetzt verstanden.
> Bei Python und dem PASS ist es wieder etwas anders, da es als> Interpreter die Anweisungen ja on the fly während der Ausführung> durchgeht und interpretiert. Ausgeführt wird hier auch nichts, aber der> Parser muß das PASS natürlich auswerten.
Ah, Ok.....in der Weise hatte ich mich nocht nicht damit
Auseinandergesetzt.
Soviel ich weiss, gibt es in Python auch noch einen "Mittelweg" zwischen
reinem Interpreter und reinem Compiler, bei dem Bytecode erzeugt wird,
der dann weiterverwendet wird.
Es würde jetzt vermutlich an Details der Umsetzung liegen, ob das
Äquivalent eines "pass" im Bytecode noch auftaucht oder nicht.
Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de
Rolf Magnus schrieb:> Bei Python und dem PASS ist es wieder etwas anders, da es als> Interpreter die Anweisungen ja on the fly während der Ausführung> durchgeht und interpretiert.
Da der Python-Quellcode vor der Ausführung in Bytecode compiliert wird,
fällt das pass komplett weg, wird also nicht in ein NOP übersetzt. So
gesehen ist pass tatsächlich eher mit der leeren Anweisung (;) in C
vergleichbar als mit dem NOP in Assembler.