Kleiner Bericht zum Umstieg von Sprache xy auf Python

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.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mechanicalStore hat geschrieben:Ich gehe davon aus, Du meinst nicht wirklich "überschreiben". Worauf ich hinaus wollte, ist:

Code: Alles auswählen

>>> class A(object):
...     staticvarA = 5
...     def printxy(self):
...         x = 'xa'
...         y = 'ya'
...         class B(object):
            staticvarB = 6
...             def printxy(self):
...                 y = 'yb'
...                 print x, y
...         b = B()
...         b.printxy()
Kann ich innerhalb B auch auf das y von a zugreifen und umgekehrt?
Ja, aber das „y von A“ ist kein „y von A“ das y gehört zu der Funktion A.printxy und nicht zu A. Der Namensraum der Klassendefinition überlebt die Klassendefinition selbst übrigens nicht. Die dort definierten Namen landen alle in dem Attribut-Dictionary der Klasse und sind nur noch über die Klasse selbst ansprechbar(deswegen musst du auch immer über self auf Attribute zugreifen, weil sie anders nicht sichtbar sind). Klassendefinitionen sind übrigens normale Code-Blöcke, du kannst da also auch for-Schleifen und allen anderen Kram verwenden. ;)

In B.printxy allerdings ist das „y von A“ nicht mehr sichtbar, da du es mit einer lokalen Variable überschrieben hast. Das kannst du verhindern indem du sie explizit mit nonlocal deklarierst(ab Python 3) verwendest.
Gleiches gilt für staticvarA und staticvarB, und; sind diese in dem Fall statisch?
Nein, es gibt keine statischen Variablen in Python. staticvarA ist eine Klassenvariable(also ein Attribut des Klassenobjekts). Klassenvariablen kannst entweder über das Klassenobjekt selbst ansprechen(A.staticvarA) oder über die Instanz (self.staticvarA). Wenn du allerdings über die Instanz diesem Attribut einen neuen Wert zuweist(self.staticVarA = 23) wird sie zu einer Instanzvariable. An den Wert der Klassenvariable kommst du dann nur noch über das Klassenobjekt.

Ist jetzt vielleicht etwas viel auf einmal, ich würd' gern noch ein Beispiel zu Verdeutlichung geben, hab allerdings dafür grade keine Zeit. :)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich halte es für weniger hilfreich, Konzepte und Verhalten operational durch deren Implementierung zu erklären. Wie __call__, __new__ usw. funktionieren, macht Dinge IMHO nur schwerer verständlich. Das einfachste Modell, was ich anbieten kann ist und bleibt, dass Klassen Funktionen sind, die Exemplare (manche nennen diese auch Instanzen, abgeleitet vom Englischen "instance") von sich erzeugen können.

Die erste Ordnung hatte ich tatsächlich mit der höheren Ordnung verwechselt.

Der Begriff "innere Klasse" ist bei Python tatsächlich ein bisschen problematisch, da es einfach anders als bei Java funktioniert, aber wenn man's einfach als das Schachteln von Klassendefinitionen versteht, dann ist das IMHO okay. Ob man auf bestimmte Variablen zugreifen kann, zeigt doch am besten ein Test. "Zugreifen" muss man natürlich erst mal genauer definieren. Lesend zugreifen ist möglich, verändern der Variablen jedoch nicht. In Python 3.x kann man mit "nonlocal" das Ändern von in einem äußeren Kontext definierten Variablen freischalten.

In dem Bespiel ist Zeile 8 falsch eingerückt. Ansonsten gilt, dass man überall mittels `A.staticVarA` und innerhalb der Methode `A.printxy` mit B.staticvarB` auf die beiden Attribute da zugreifen kann. Gäbe es da nicht die Methode `A.printxy`, sondern wäre B direkt innerhalb von A definiert (wie man es auch meist in Java sieht), könnte man mit `A.B.staticvarB` direkt zugreifen. Im Gegensatz zu Java funktionieren da allerdings nicht die kurzeren Namen, da Python diese für lokale Variablen halten würde.

Ach und mein Rant gegen das `-*-`: Ich weigere mich auch in Zukunft, ich in meinen Quelltext Beschwörungsformeln für archaische Editoren einzubauen, nur weil jemand nicht UTF-8 als längst überfälligen Standard akzeptieren kann. Wenn ich sehe, wie viele Probleme Leute hier immer wieder mit Encoding-spezifischen Problemen haben, dann ist das ein ganz klares Zeichen dafür, dass weniger Freiheitsgrade hier echt helfen würden.

Stefan
BlackJack

@mechanicalStore: Welches `y` von `a`? Ich sehe nur zwei `y`\s und zwar jeweils lokale Namen in Funktionen/Methoden. Die Klassen machen das Beispiel nur verwirrender, machen da aber letztendlich keinen grossen Unterschied zu einem Beispiel wo bloss zwei Funktionen verschachtelt wären. Die Regeln zur Namensauflösung bleiben die gleichen. Die solltest Du vielleicht nicht an so einem komplizierten Beispiel üben.

Dann ist Deine Frage IMHO ein wenig unpräzise gestellt. Was meinst Du mit "innerhalb B auch auf das y von a zugreifen und umgekehrt"? Innerhalb von `B` ist für mich der Code auf Klassenebene von `B`, der bei der Ausführung der ``class``-Anweisung ausgeführt wird. Der kann, nach den ganz normalen Regeln, lesend auf das lokale `y` von `A.printxy()` zugreifen. Umgekehrt? Die Klasse `B` hat kein `y`, also weder die Klasse noch Exemplare davon!?

Auf `staticvarA` kann man sowohl von `B` als auch von Exemplaren von `B` natürlich zugreifen, über `A.staticvarA` beziehungsweise in der Klassendefinition von `B` auch zusätzlich noch über `self.staticvarA`. Was allerdings etwas verwirrend auf den Leser wirken könnte.

Von einem Exemplar von `A` aus kommt man an `B.staticvarB` grundsätzlich in dem Beispiel nicht heran, weil `B` ja ein lokaler Name in `A.printxy()` ist. Das ist halt mit lokalen Namen von Funktionen so, dass man da von aussen nicht dran kommt. Ist ja auch "normal", soll heissen in anderen Sprachen auch üblich. Innerhalb von `A.printxy()` kann man auf `B.staticvarB` natürlich zugreifen sobald die ``class``-Anweisung ausgeführt wurde.

`staticvarA` und `staticvarB` sind nicht statisch, weil bei Python alles dynamisch ist. Klassen sind nicht statisch, wie können es da Attribute auf Klassen sein!? Die Namen sind also irreführend gewählt.

Und zum Schluss noch einmal: Die ``class``-Anweisung wird *ausgeführt*, zur Laufzeit, *jedes* mal wenn der Programmfluss an der Anweisung vorbeikommt! Das ist *keine* Deklaration! Und ``class`` und ``def`` können halt als Anweisungen überall da im Quelltext stehen, wo alle anderen Anweisungen auch stehen können.

Edit: Ups *viel* zu spät. :-)
mechanicalStore
User
Beiträge: 116
Registriert: Dienstag 29. Dezember 2009, 00:09

sma hat geschrieben: Ach und mein Rant gegen das `-*-`: Ich weigere mich auch in Zukunft, ich in meinen Quelltext Beschwörungsformeln für archaische Editoren einzubauen, nur weil jemand nicht UTF-8 als längst überfälligen Standard akzeptieren kann. Wenn ich sehe, wie viele Probleme Leute hier immer wieder mit Encoding-spezifischen Problemen haben, dann ist das ein ganz klares Zeichen dafür, dass weniger Freiheitsgrade hier echt helfen würden.
Stefan
In diesem Zusammenhang, wenn ich probiere, was in http://docs.python.org/tutorial/interpr ... e-encoding steht. Ich habe IDLE in den options auf utf-8 eingestellt.

Code: Alles auswählen

IDLE 2.6.2      ==== No Subprocess ====
>>> currency = u"€"
>>> print currency
€
>>> print ord(currency)
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    print ord(currency)
TypeError: ord() expected a character, but string of length 3 found
>>> 
Wieso kommt IDLE nicht mit ord() klar, wenn doch utf-8 eingestellt ist? Und wieso wird das Euro-Zeichen beim print nicht ausgegeben?

Schönen Gruß
mechanicalStore
User
Beiträge: 116
Registriert: Dienstag 29. Dezember 2009, 00:09

BlackJack hat geschrieben: `staticvarA` und `staticvarB` sind nicht statisch, weil bei Python alles dynamisch ist. Klassen sind nicht statisch, wie können es da Attribute auf Klassen sein!? Die Namen sind also irreführend gewählt.
Sorry, hab mich unklar ausgedrückt. Richtig ist aber doch, dass staticvarA und staticvarB Klassenvariablen sind?! Da Klassenvariablen z.B in Java mit static deklariert werden, neige ich meisst dazu, sie mit "statische Variablen" zu bezeichnen.

Schönen Gruß
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Meine bpython-Session:

Code: Alles auswählen

>>> curr = u"€"
>>> curr
u'\u20ac'
>>> print curr
€
>>> ord(curr)
8364
>>>
Das Problem ist schlicht, dass das Encoding nicht passt, d.h. deine IDLE Einstellungen passen nicht, woran es liegt kann ich dir allerdings nicht sagen, da ich IDLE grossraeumig umfahre.

Ja, Klassenvariablen sind mit Java `static` vergleichbar, allerdings sollte man sich hueten Vergleiche mit statischen Sprachen staendig heranzuziehen, da das eine andere Welt ist. In Python gibt es - wie schon haeufig angesprochen - keine Deklarationen, sondern nur ausfuehrbaren Code. Ebenfalls keine Qualifier. Das sollte man versuchen zu verstehen und nicht auf Sprachen ausweichen, die das nicht kennen.

Warum Tupel und Listen? Die einfachste Antwort duerfte sein, dass die Sprache reichlich Tupel verwendet. Die naechste Stufe, dass sie effizienter implementiert werden koennen als Listen.
Fuer mich kommt dazu noch die semantische Ebene und so den Source verstaendlicher machen koennen.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mechanicalStore hat geschrieben:Wieso kommt IDLE nicht mit ord() klar, wenn doch utf-8 eingestellt ist? Und wieso wird das Euro-Zeichen beim print nicht ausgegeben?
Weil da irgendwas kaputt ist, von IDLE hört man hier sowieso immer nur die wildesten Sachen, also lieber nicht benutzen. Dasselbe Problem habe ich aber auch mit ipython unter OSX(ipython ist unter OSX sowieso immer etwas broken, liegt vermutlich an readline/libedit). Ich behelfe mich mit "€".decode("utf8").
Sorry, hab mich unklar ausgedrückt. Richtig ist aber doch, dass staticvarA und staticvarB Klassenvariablen sind?! Da Klassenvariablen z.B in Java mit static deklariert werden, neige ich meisst dazu, sie mit "statische Variablen" zu bezeichnen.
Ja. Allerdings sind statische Variablen und Methoden etwas anderes als Klassenmethoden und -variablen. Klassenmethoden operieren auf dem Klassenobjekt. Statische Methoden in Java sind allerdings wirklich nur Funktionen. Die Klasse steht in statischen Methoden nicht als this zur Verfügung. Späße wie Vererbung funktionieren deswegen nicht wirklich gut mit statischen Methoden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich muss sma da jetzt aber auch beipflichten -- dem Einsteiger ist jetzt nicht geholfen, dass wir uns über Details unterhalten was jetzt hashbar ist und was nicht oder wie sich das auf die Objektidentität auswirkt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mechanicalStore
User
Beiträge: 116
Registriert: Dienstag 29. Dezember 2009, 00:09

Leonidas hat geschrieben:Ich muss sma da jetzt aber auch beipflichten -- dem Einsteiger ist jetzt nicht geholfen, dass wir uns über Details unterhalten was jetzt hashbar ist und was nicht oder wie sich das auf die Objektidentität auswirkt.
Nee nee, das ist kein Problem. Während man aus der Doku ohnehin nur Dinge wie die Syntax und Semantik erfährt, sind solche Diskussionen durchaus nützlich, um Weiteres über das Verhalten von Python zu erfahren, man (ich) kann also nur daraus lernen.

@lunar:

Code: Alles auswählen

class Foo(object):
    def __init__(self, x):
        self.value = x
    def __hash__(self):
        return hash(self.value)
    def __eq__(self, other):
        return self.value == other.value
    def __ne__(self, other):
         return self.value != other.value

f = Foo('hallo')
d = {f: 'welt'}
f.value = 'tschüss'
d[f] # <-- ergibt KeyError, weil sich der Hash von f geändert hat
Mir ist nicht ganz klar, was hier passiert. __init__ ist mir ja schon bekannt. Sind die anderen Funktionen ebenfalls Standard und werden hier überschrieben?
Was genau bewirkt die Anweisung d = {f: 'welt'}, das ist eine mir sehr unbekannte Syntax.

Schönen Gruß
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@mechanicalStore Methodennamen die mit zwei Unterstrichen beginnen und enden, bezeichnen sogenannte Special Methods, die werden im Data model erklärt.

Dort findest du außerdem Erklärungen zur Implementation von Deskriptoren etc.

In Zeile 13 des Codes wird ein Dictionary erstellt und an einen Namen gebunden, f dient dabei als Schlüssel für den Wert 'welt'.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mechanicalStore hat geschrieben:Während man aus der Doku ohnehin nur Dinge wie die Syntax und Semantik erfährt, sind solche Diskussionen durchaus nützlich, um Weiteres über das Verhalten von Python zu erfahren, man (ich) kann also nur daraus lernen.
Zur Doku gehoert auch die Sprachspezifikation, alles was dort nicht enthalten ist, sollte sowieso mit Vorsicht zu geniessen sein, da hoechstwahrscheinlich Implementierungsdetail von CPython. Wobei man so natuerlich auf die Hintergruende schliessen (lese: raten) kann.

Die Dunder (double underscore) Attribute sind "magic". Im Klartext heisst das, dass das spezielle Methoden sind, die der Interpreter als solche erkennt die einem Objekt spezielle Eigenschaften verpassen, sozusagen Protokolle/Interfaces.

Mehr Infos: http://docs.python.org/reference/datamo ... thod-names
http://www.ironpythoninaction.com/magic-methods.html
mechanicalStore hat geschrieben:Was genau bewirkt die Anweisung d = {f: 'welt'}, das ist eine mir sehr unbekannte Syntax.
Auf der rechten Seite ist ein Dictionary Literal und der rest ist eine Zuweisung. Der Kern des Snippets ist natuerlich, dass `f` hier hashable scheint - `__hash__` implementiert - es aber nicht wirklich ist.

[Edit (Leonidas): Restliche Diskussion zu Tupeln und Listen in Hashable objects abgetrennt]
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

sma hat geschrieben:Ach und mein Rant gegen das `-*-`: Ich weigere mich auch in Zukunft, ich in meinen Quelltext Beschwörungsformeln für archaische Editoren einzubauen, nur weil jemand nicht UTF-8 als längst überfälligen Standard akzeptieren kann.
In Emacs ist utf-8 Standard... Aber darum ging es in BlackJacks Antwort ja auch nicht.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

mechanicalStore hat geschrieben:Was genau bewirkt die Anweisung d = {f: 'welt'}, das ist eine mir sehr unbekannte Syntax.
Das steht für

Code: Alles auswählen

d = {}
d[f] = 'welt'

#oder
d = dict()
d[f] = 'welt'
Links vom ":" ist der Schlüssel, rechts davon der Welt. Beides könnten beliebige Objekte sein, allerdings hat man - wie hier ja zu genüge erläuert - wenig Freude daran, wenn das Schlüsselobjekt veränderbar, aber nicht "hashable" ist. Und damit kommen wir zu einer der ursprünglichen Fragen zurück: Warum es sinnvoll ist, dass Objekte unveränderbar sind. Dann haben sie in der Regel (wenn sie auch nur unveränderbare Objekte enthalten) einen vernünftigen Hash-Wert und können al Schlüssel in einem Dictionary benutzt werden.

Stefan
mechanicalStore
User
Beiträge: 116
Registriert: Dienstag 29. Dezember 2009, 00:09

sma hat geschrieben:
Das steht für

Code: Alles auswählen

d = {}
d[f] = 'welt'

#oder
d = dict()
d[f] = 'welt'
Links vom ":" ist der Schlüssel, rechts davon der Welt. Beides könnten beliebige Objekte sein, allerdings hat man - wie hier ja zu genüge erläuert - wenig Freude daran, wenn das Schlüsselobjekt veränderbar, aber nicht "hashable" ist. Und damit
Das macht es klarer, vielen Dank. Der Doppelpunkt hatte mich verwirrt. Nun habe ich mal eine andere Frage; Unter http://www.tortall.net/mu/wiki/CairoTutorial gibt es ein Beispiel, dessen Code ich mal teilweise poste:

Code: Alles auswählen

#! /usr/bin/env python
import cairo
from math import pi, sqrt

class Diagram(object):
    def __init__(self, filename, width, height):
        self.surface = cairo.SVGSurface(filename + '.svg', width, height)
        cr = self.cr = cairo.Context(self.surface)

        cr.scale(width, height)
        cr.set_line_width(0.01)

        cr.rectangle(0, 0, 1, 1)
        cr.set_source_rgb(1, 1, 1)
        cr.fill()

**      self.draw_dest(cr)

        cr.set_line_width( max(cr.device_to_user_distance(2, 2)) )
        cr.set_source_rgb(0, 0, 0)
        cr.rectangle(0, 0, 1, 1)
        cr.stroke()

        self.surface.write_to_png(filename + '.png')
        cr.show_page()
        self.surface.finish()

class SetSourceRGBA(Diagram):
    def draw_dest(self, cr):
        cr.set_source_rgb(0, 0, 0)         #rgba
        cr.move_to(0, 0)                   #rgba
        cr.line_to(1, 1)                   #rgba
        .....

if __name__ == '__main__':
    size = 120
    SetSourceRGBA('setsourcergba', size, size)
Frage zur letzten Zeile: Wird hier die Klasse tatsächlich "nur" als Funktion aufgerufen (da keine Instanzierung stattfindet)? Wie aber kann man dann self benutzen?

Wird durch diesen Aufruf automatisch die __init__ Methode der Basisklasse (Diagram) aufgerufen (ich frage, weil ich meine mich zu erinnern, dass irgendwo gesagt wurde, dass das nicht so ist und man sich selbst darum kümmern muss, dass der Konstruktor der Basisklasse aufgerufen wird)?

Ist es nicht sehr unsauber, im Konstruktor der Basisklasse in der Zeile ** eine Methode der erbenden Klasse aufzurufen?

Bedeutet folgende Zeile im Kontruktor

Code: Alles auswählen

cr = self.cr = cairo.Context(self.surface)
dass self.cr eine Instanzvariable und cr eine Klassenvariable ist? Falls ja, hätte man in dem Fall cr nicht auf der (Einrück)-Ebene im Hauptblock (also auf der Ebene, wo auch __init__ deklariert wurde) deklarieren müssen?

Schönen Gruß
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

mechanicalStore hat geschrieben:Frage zur letzten Zeile: Wird hier die Klasse tatsächlich "nur" als Funktion aufgerufen (da keine Instanzierung stattfindet)? Wie aber kann man dann self benutzen?
Doch, hier wird ein Exemplar von SetSourceRGBA erzeugt, aber dieses wird an keinen Bezeichner gebunden.
mechanicalStore hat geschrieben:Wird durch diesen Aufruf automatisch die __init__ Methode der Basisklasse (Diagram) aufgerufen (ich frage, weil ich meine mich zu erinnern, dass irgendwo gesagt wurde, dass das nicht so ist und man sich selbst darum kümmern muss, dass der Konstruktor der Basisklasse aufgerufen wird)?
Letzteres gilt nur dann, wenn eine Klasse eine eigene __init__()-Methode hat. Hat sie keine (so wie hier), wird automatisch diejenige der Basisklasse verwendet.
mechanicalStore hat geschrieben: Bedeutet folgende Zeile im Kontruktor

Code: Alles auswählen

cr = self.cr = cairo.Context(self.surface)
dass self.cr eine Instanzvariable und cr eine Klassenvariable ist?
Nein, cr ist eine lokale Variable.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

SetSourceRGBA erbt von Diagram und Diagram hat eine __init__, die aufgerufen wird.

`cr = self.cr = cairo.Context(self.surface)` bewirkt, dass das Objekt sowol an das Objekt gebunden wird als auch als kurzer Name (cr) zur Verfügung steht. Da war wohl jemand zu faul immer self.cr zu schreiben.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mechanicalStore hat geschrieben: Wird durch diesen Aufruf automatisch die __init__ Methode der Basisklasse (Diagram) aufgerufen (ich frage, weil ich meine mich zu erinnern, dass irgendwo gesagt wurde, dass das nicht so ist und man sich selbst darum kümmern muss, dass der Konstruktor der Basisklasse aufgerufen wird)?
Wenn die abgeleitete Klasse keine __init__-Methode hat, dann wird die der Basisklasse aufgerufen. Hätte die abgeleitete Klasse eine solche Methode so würde die der Basisklasse nur aufgerufen, wenn das in der abgeleiteten Klasse so programmiert wäre.
mechanicalStore hat geschrieben:Ist es nicht sehr unsauber, im Konstruktor der Basisklasse in der Zeile ** eine Methode der erbenden Klasse aufzurufen?
Nein. Zumindest ich sehe das nicht als problematisch an, sondern eher als das, was Objektorientierung mit ausmacht.
mechanicalStore hat geschrieben: Bedeutet folgende Zeile im Kontruktor

Code: Alles auswählen

cr = self.cr = cairo.Context(self.surface)
dass self.cr eine Instanzvariable und cr eine Klassenvariable ist?
Nein. cr ist nur im Konstruktor bekannt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

/me hat geschrieben:
mechanicalStore hat geschrieben:Ist es nicht sehr unsauber, im Konstruktor der Basisklasse in der Zeile ** eine Methode der erbenden Klasse aufzurufen?
Nein. Zumindest ich sehe das nicht als problematisch an, sondern eher als das, was Objektorientierung mit ausmacht.
Das mag sein, aber da man direkt Klassen von `Diagram` erstellen kann, finde ich das durchaus unsauber.
IMHO sollte man ein `draw_dest` in `Diagram` erstellen, das einen `NotImplementedError` schmeisst oder vergleichbares.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

mechanicalStore hat geschrieben:Frage zur letzten Zeile: Wird hier die Klasse tatsächlich "nur" als Funktion aufgerufen (da keine Instanzierung stattfindet)?
Wieso sollte keine Instanzierung stattfinden? Wie sma schon schrieb, eine Klasse gibt, wenn man sie „wie eine Funktion aufruft“ eine Instanz von sich selbst zurück(das Verhalten ließe sich natürlich ändern, da Klassen auch nur Objekte wie alle anderen sind). Wie genau das geschieht, kann dir erstmal egal sein.
Ist es nicht sehr unsauber, im Konstruktor der Basisklasse in der Zeile ** eine Methode der erbenden Klasse aufzurufen?
Jein, dass macht deine Klasse nur schlicht und ergreifend zu einer abstrakten Klasse. Aber wie schon geschrieben, wäre es besser, die Methode in der Basisklasse zu implementieren und einen NotImplementedError zu werfen, das macht die Fehlermeldungen aussagekräftiger bzw. man man ggf. besser auf den Fehler reagieren.

Code: Alles auswählen

cr = self.cr = cairo.Context(self.surface)
dass self.cr eine Instanzvariable und cr eine Klassenvariable ist? Falls ja, hätte man in dem Fall cr nicht auf der (Einrück)-Ebene im Hauptblock (also auf der Ebene, wo auch __init__ deklariert wurde) deklarieren müssen?
cr ist eine stinknormale lokale Variable. Es gibt keinen Grund, warum das nicht so sein sollte. Warum

Warum er das überhaupt macht, liegt daran, dass Attributzugriffe in Python relativ teuer sind. Wenn eine Funktion oft aufgerufen wird kann schon Zeit sparen, wenn man dort oft verwendete Attribute lokal „cached“. Man sollte das aber auch nicht überstrapazieren(premature optimization...)
Zuletzt geändert von Darii am Montag 4. Januar 2010, 21:05, insgesamt 4-mal geändert.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

oh, ich wollte auch lokal schreiben.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Antworten