Ungebunden kommt vor Gebunden

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.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

jerch hat geschrieben:Fraglich ist noch, ob das Verhalten nur für direkte Typnachfolger von Metaklassen oder für Klassentypen generell gilt.
...
Habs mal kurz getestet, scheint tatsächlich generell für Klassentypen zu gelten.
EyDu hat geschrieben:Hier wird gar nichts unterschiedlich behandelt. Erst werden die Attribute im Objekt gesucht, dann in den Klassen entsprechend der Vererbungshierarchie.

Ich würde jetzt im Nachhinein auch sagen, das Verhalten gilt ganz allgemein, und je länger ich darüber nachdenke, desto logischer kommt es mir vor. Ein ganz einfaches Beispiel (ohne Metaklassen) wäre:

Code: Alles auswählen

class K(object):
  foo = lambda oK,verwirf: "Klassenfunktion"
#
oK = K()
oK.foo = lambda verwirf: "Objektfunktion"


#"Objektsuche VOR Klassensuche:
print oK.foo(None)  #druckt "Objektfunktion" aus
Da Klassen selber "nur" von Metaklassen erzeugte Objekte sind, gilt parallel zum obigen Beispiel auch das Beispiel:

Code: Alles auswählen

class mK(type):
  foo = lambda K,verwirf: "Klassenfunktion"
#
class K(object):
  __metaclass__ = mK
  foo = lambda verwirf: "Objektfunktion"
#
oK = K()


#"Objektsuche VOR Klassensuche:
print K.foo(oK)  #druckt "Objektfunktion" aus
Das einzige, was zu beachten ist, ist dass Klassenaufrufen (gleich welcher Art) immer eine Instanz der Klasse hinzuzufügen ist.
Zuletzt geändert von Goswin am Dienstag 28. April 2009, 13:48, insgesamt 3-mal geändert.
Python nervt. (Nicht immer, und natürlich nur mich, niemals andere)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Vielleicht hilft euch das bei euren Spekulationen auf die Sprünge:

Code: Alles auswählen

>>> class Meta(type):
...     pass
...
>>> class Spam(object):
...     __metaclass__ = Meta
...
>>> s = Spam()
>>> type(s)
<class '__main__.Spam'>
>>> type(Spam)
<class '__main__.Meta'>
>>> isinstance(s, Spam)
True
>>> isinstance(s, Meta)
False
Das Leben ist wie ein Tennisball.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@EyDu:
Naja, das war schon klar.

Der Hund liegt trotzdem in der Typenhierarchie begraben, für Klassen findet Python das Metaklassenattribut via type(Klasse).__dict__, für Objekte dagegen nicht (das Metaklassenattribut wäre erst mit type(type(obj)) zu finden).
In meinen Augen ist das schon ein Unterschied in der Behandlung, zumal die Dokumentation die Metaklassen explizit rausnimmt (allerdings wird auch nur von objects geredet). Ob dieser Unterschied nun hard kodiert ist oder strukturell bedingt ist, ist für mich als Anwender der Sprache egal, da die Phänomenologie entscheidend ist.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Welcher Hund denn nun wieder?
Attribute werden in
a) Instanzen
b) Klassen
c) Eltern-klassen
gesucht:

Code: Alles auswählen

# Beispiel zur Verwirrung
class Meta(type):
    obscure_attr = "In Meta"
class Foo(object):
    foo_attr = "In Foo"
class Bar(Foo):
    bar_attr = "In Bar"
class Bar2(object):
    bar_attr = "In Bar2"
class Baz(Bar, Bar2):
    __metaclass__ = Meta
    baz_attr = "In Baz"
    def __init__(self):
        self.inst_attr="In baz-instance"
a_single_instance = Baz()
#geht:
print a_single_instance.inst_attr #logisch
print a_single_instance.baz_attr
print a_single_instance.foo_attr
#geht nicht:
try:
    print a_single_instance.obscure_attr
except AttributeError, ex:
    print ex.message
#geht:
print Baz.obscure_attr
# DENN: Baz IST eine Instanz von Meta()!
print isinstance(Baz, Meta)
hth, Jörg
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

jerch hat geschrieben:Der Hund liegt trotzdem in der Typenhierarchie begraben,
Ja natürlich liegt das an der Typhierarchie. Das sich zwei Objekte die unterschiedliche Attribute/Typen/etc. haben sich unterschiedlich verhalten sollte eigentlich niemanden Verwundern. Und du solltest auch nicht zwischen Objekten und Klassen unterscheiden sondern lieber zwischen Instanzen und Klassen, Objekte sind nämlich beide.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und? Da ist immer noch nichts magisches.

Ich mach es mal noch ein wenig einfacher:

Code: Alles auswählen

>>> class Meta(type):
	pass

>>> class Spam(object):
	__metaclass__ = Meta

	
>>> Spam.__base__
<type 'object'>
Metaklasen kommen nicht in der Klassenhierarchie vor.
Das Leben ist wie ein Tennisball.
Antworten