Mir fällt gerade auf, als ich eine membervariable self.header eingeführt hatte und eine
methode header() definiert hatte. Das scheint nicht erlaubt zu sein.
Klassenmethode kann nicht gleichzeiting Membername sein?
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Und du suchst jetzt eine Bestaetigung? Ja, ein Name/Attribut kann immer nur auf ein Objekt verweisen. Aber verboten ist es deshalb nicht. Man darf sich damit gerne selbst ins Knie schiessen.
So, warum macht es keinen Sinn dass der Name auf 2 Objekte verweisen koennte? Weil der Zugriffsweg derselbe ist. Du kannst an ein Attribut beliebige Werte zuweisen, u.a. auch Funktionen. Wie soll man dann zwischen dem Aufruf der "richtigen" Methode `Klass.header` und dem Aufruf einer Funktion, die an `klass.header` gebunden ist, unterscheiden?
So, warum macht es keinen Sinn dass der Name auf 2 Objekte verweisen koennte? Weil der Zugriffsweg derselbe ist. Du kannst an ein Attribut beliebige Werte zuweisen, u.a. auch Funktionen. Wie soll man dann zwischen dem Aufruf der "richtigen" Methode `Klass.header` und dem Aufruf einer Funktion, die an `klass.header` gebunden ist, unterscheiden?
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@Krischu:Das ist doch irgendwie klar, denn wie sollte ein Objekt denn auch mehrere Attribute mit dem gleichen Namen haben? Methoden benennt man üblicherweise auch nach Tätigkeiten, denn die tun ja etwas. Für `header()` gibt es also vielleicht einen besseren Namen der dem Leser verrät was die Methode tut.
indem ich sagecofi hat geschrieben:Und du suchst jetzt eine Bestaetigung? Ja, ein Name/Attribut kann immer nur auf ein Objekt verweisen. Aber verboten ist es deshalb nicht. Man darf sich damit gerne selbst ins Knie schiessen.
So, warum macht es keinen Sinn dass der Name auf 2 Objekte verweisen koennte? Weil der Zugriffsweg derselbe ist. Du kannst an ein Attribut beliebige Werte zuweisen, u.a. auch Funktionen. Wie soll man dann zwischen dem Aufruf der "richtigen" Methode `Klass.header` und dem Aufruf einer Funktion, die an `klass.header` gebunden ist, unterscheiden?
Code: Alles auswählen
klass.header - damit greife ich direkt auf self.header zu (auch komisch, daß ich von draußen drauf zugreifen kann, aber gut
Python hat keine private members.
klass.header() - ist der Methodenaufruf. Was wäre daran verboten?
--
Grüße
Christoph
Grüße
Christoph
Python benötigt keine privaten Attribute, dass wird über Konvention geregelt. Wenn du etwas als Implementierungsdetail kennzeichen willst, dann benutze Namen mit einem führenden Unterstrich.Krischu hat geschrieben:code=python file=Untitled.py]klass.header - damit greife ich direkt auf self.header zu (auch komisch, daß ich von draußen drauf zugreifen kann, aber gut Python hat keine private members.
Weil die Namensauflösung in Python anders funktioniert. Mit ``klass.header`` holst du dir das header-Attribut von "klass". Dabei kann "header" alles mögliche sein: ein Integer, ein Float oder auch etwas Aufrufbares wie eine Methode (Funktionen sind in Python First-Class-Objekte). Wenn du also ``klass.header()`` schreibst, dann holst du dir das header-Objekt und rufst dieses auf. Was konkret bedeutet, dass du die __call__-Methode von "header" aufrufst.Krischu hat geschrieben:klass.header() - ist der Methodenaufruf. Was wäre daran verboten?
Code: Alles auswählen
>>> class Spam(object):
... def ham(self, x):
... print x
...
>>> s = Spam()
>>> h = s.ham
>>> h(42)
42
>>> h.__call__(42)
42
Das Leben ist wie ein Tennisball.
oder der gegenteilige Fall:
Code: Alles auswählen
>>> class Spam(object):
... def __init__(self):
... self.ham = None
...
>>> def egg(x):
... print x
...
>>> spam = Spam()
>>> spam.ham = egg
>>> spam.ham(42)
42
>>>
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Du kannst natürlich auch ``self.header = 42`` setzen und dann versuchen ``self.header()`` aufzurufen und gucken was passiert. Tipp: 42 ist nicht "callable".
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Wenn man mal nicht über Sinn oder Unsinn einer solchen Aktion nachdenkt: Wo genau ist die Stelle, an der man sich einklinken müsste, um zu ermitteln, ob ein Name abgefragt oder aufgerufen wird, sprich ob Klammern gesetzt sind oder nicht?
mutetella
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit
)

Meinst Du so was?mutetella hat geschrieben:Wo genau ist die Stelle, an der man sich einklinken müsste, um zu ermitteln, ob ein Name abgefragt oder aufgerufen wird, sprich ob Klammern gesetzt sind oder nicht?
Code: Alles auswählen
>>> class A(object):
... b = 42
... def c(self):
... pass
...
>>> a = A()
>>> type(a.b)
<type 'int'>
>>> type(a.c)
<type 'instancemethod'>
@mutetella: Da gibt es keine Stelle denn ein Attribut wird immer erst mit dem Punktoperator abgefragt, egal ob es ein ”Datenattribut” oder eine gebundene Methode ist. Und ob und wann das Objekt dann aufgerufen wird, sagt einem immer noch nicht ob es sich um eine Methode dieses Objekts oder ein ”Datenattribut” handelt. Und da der Punktoperator und das Aufrufen komplett voneinander unabhängig sind, kann man auch nicht Unterscheiden ob der Abrufer des Attributs ein ”Datenattribut” oder eine Methode haben wollte, wenn man denn diese zwei ”verschiedenen” Sachen unter dem selben Attributnamen anbieten möchte.
- diesch
- User
- Beiträge: 80
- Registriert: Dienstag 14. April 2009, 13:36
- Wohnort: Brandenburg a.d. Havel
- Kontaktdaten:
Methoden sind in Python normale Objekte wie Strings, Zahlen usw. auch. Ich kann daher so was schreiben:
Code: Alles auswählen
class Foo:
def __init__(self):
self.a = 42
def b(self):
return 17
foo=Foo()
for name in 'a', 'b':
attr = getattr(foo, name)
if callable(attr):
value = attr()
else:
value = attr
print('%s: %s' % (name, value))
http://www.florian-diesch.de
@BlackJack:
Keine Stelle, die ich mit Pythonmitteln erreiche oder generell keine, bzw. nur, wenn ich den Interpreter verändere?
mutetella
Keine Stelle, die ich mit Pythonmitteln erreiche oder generell keine, bzw. nur, wenn ich den Interpreter verändere?
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit
)

@mutetella: Vielleicht solltest Du noch mal genau beschreiben was Du erreichen willst. Ob ein Name abgefragt oder (das Objekt hinter einem Namen) aufgerufen wird ist jedenfalls keine sauber getrennte Unterscheidung, weil aufrufen in diesem Fall immer ein abfragen vorausgehen muss. ``obj.spam()`` ist nicht eine Operation sondern zwei, das kann man auch entsprechend Klammern um es zu verdeutlichen: ``(obj . spam)()``. Das ist legale Python-Syntax.
Und ob ein abgefragtes Attribut aufgerufen wird: Wie willst Du das testen. Das muss ja auch nicht zwingend direkt nach dem Abfragen passieren wie von anderen ja hier schon an Beispielen gezeigt wurde.
Und ob ein abgefragtes Attribut aufgerufen wird: Wie willst Du das testen. Das muss ja auch nicht zwingend direkt nach dem Abfragen passieren wie von anderen ja hier schon an Beispielen gezeigt wurde.
@BlackJack
Ich meine, ob sowas in dieser Art machbar wäre:
mutetella
Ich meine, ob sowas in dieser Art machbar wäre:
Code: Alles auswählen
class Nonsense(object):
def __init__(self):
self._multiple = ('any_value', self.any_callable)
def any_callable(self, value):
pass
@property
def multiple(self):
request_has_brackets, value = interpreter.please_give_it_to_me()
if request_has_brackets:
return self._multiple[1](value)
return self._multiple[0]
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit
)

- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
@mutetella: Nein, das laesst die Semantik nicht zu. Wie BlackJack schon geschrieben hat, sind es zwei Operationen, die man u.a. auch trennen kann.
Selbst wenn man den Zugriff auf Methoden und Datenattributen noch durch einen moeglichen Aufruf unterscheiden koennte: Das ist zu kurz gegriffen, denn man verbietet damit zum einen callables als Datenattribute und zum anderen den blossen Zugriff auf die Methoden-Objekte.
Was man machen koennte ist, manuell 2 Namensraeume fuer Daten und Methoden einzufuehren ... nur braeuchte man dann zumindest fuer eines einen eigenen Zugriffweg, sonst steht man wieder vor dem Problem von oben.
Selbst wenn man den Zugriff auf Methoden und Datenattributen noch durch einen moeglichen Aufruf unterscheiden koennte: Das ist zu kurz gegriffen, denn man verbietet damit zum einen callables als Datenattribute und zum anderen den blossen Zugriff auf die Methoden-Objekte.
Was man machen koennte ist, manuell 2 Namensraeume fuer Daten und Methoden einzufuehren ... nur braeuchte man dann zumindest fuer eines einen eigenen Zugriffweg, sonst steht man wieder vor dem Problem von oben.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@mutetella: Nein das ist nicht möglich, das hätte aber aus den bisherigen Beiträgen schon ersichtlich sein müssen, denn ob und wann das abgefragte Objekt aufgerufen wird kann der Interpeter beim Abfragen ja nicht ermitteln. Das kann ja irgendwann an einer ganz anderen Stelle im Code passieren und muss nicht direkt nach dem Abfragen des Attributs passieren. Warum Du im Falle von `request_has_brackets` das zweite Objekt in dem Tupel *aufrufst* ist mir auch nicht so ganz klar, denn dann muss das selber ja wieder etwas aufrufbares zurückgeben weil der Code der diesen Rückgabewert bekommt, ihn ja offensichtlich aufrufen wird, sonst wäre `request_has_brackets` nicht wahr.
Was Du im Grunde fragst ist ob eine Funktion/Methode herausfinden kann was der Aufrufer mit ihrem Rückgabewert machen wird. Nein, das geht nicht, weil das nicht vorgesehen ist. Das wäre auch ziemlich schräg.
Was Du im Grunde fragst ist ob eine Funktion/Methode herausfinden kann was der Aufrufer mit ihrem Rückgabewert machen wird. Nein, das geht nicht, weil das nicht vorgesehen ist. Das wäre auch ziemlich schräg.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Vielleicht ist es doch möglich, wenn man im aufrufenden Stackframe schaut was das noch für Bytecodes hat und ob danach ein Funktionsaufruf kommt. So ähnlich wie birkenfeld ``runkit_return_value_used`` implementiert hat 

My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@Leonidas: Ich ging davon aus das wir von Python reden und nicht von Interna einer bestimmten Implementierung wo man schmutzige Hacks anwenden kann. 

Also so schmutzig ist dass gar nicht, nachdem man die Magie hinter einer Metaklasse versteckt hat 

Code: Alles auswählen
import sys
import dis
import inspect
NO_ATTRIBUTE = object()
class SeparateNamedspacedMeta(type):
def __new__(cls, name, bases, attributes):
_methods = {}
for name, attribute in attributes.iteritems():
if name.startswith('__') and name.endswith('__'):
continue
if inspect.isfunction(attribute):
_methods[name] = attribute
attributes[name] = AttributeOrMethodDescriptor(name)
attributes['_methods'] = _methods
return type.__new__(cls, name, bases, attributes)
class AttributeOrMethodDescriptor(object):
def __init__(self, name):
self.name = name
self.attribute_value = NO_ATTRIBUTE
def __get__(self, instance, owner):
if instance is None or self.attribute_value is NO_ATTRIBUTE:
return owner._methods[self.name].__get__(instance, owner)
calling_frame = sys._getframe(1)
next_opcode = ord(calling_frame.f_code.co_code[calling_frame.f_lasti + 3])
if dis.opname[next_opcode] == 'CALL_FUNCTION':
return owner._methods[self.name].__get__(instance, owner)
return self.attribute_value
def __set__(self, instance, value):
self.attribute_value = value
def __delete__(self, instance):
self.attribute_value = NO_ATTRIBUTE
class SeparateNamespacedClass(object):
__metaclass__ = SeparateNamedspacedMeta
def __init__(self):
self.spam = 'attribute'
def spam(self):
return 'method'
foo = SeparateNamespacedClass()
print SeparateNamespacedClass.spam # <unbound method spam.spam>
print foo.spam # attribute
print foo.spam() # method
Egal was man da drumherum an Magie veranstaltet: ``next_opcode = ord(calling_frame.f_code.co_code[calling_frame.f_lasti + 3])`` wird unter Jython, IronPython, und PyPy wohl nicht funktionieren. Das ist halt ein Implementierungsdetail von CPython. `sys._getframe()` kann man ja im Grunde schon nicht als gegeben ansehen. Und es löst nicht das Problem das man manchmal auch die Methode haben möchte ohne sie direkt aufzurufen.