Hier sind zwei Probleme zur Hand. Erstens muss eine Funktion, die in eine Methode umgewandelt werden soll, in der Klasse gespeichert werden, nicht in der Instanz. Eine Demonstration:
>>> x.a('a will have "self"')
a (<__main__.Foo object at 0x100425ed0>, 'a will have "self"')
>>> x.b('as will b')
b (<__main__.Foo object at 0x100425ed0>, 'as will b')
>>> x.c('c will only recieve this string')
c ('c will only recieve this string',)
Wie Sie es wenig Unterschied zwischen einer Funktion sehen kann zusammen mit der Klasse definiert, und ein später zugeordnet. Ich glaube, es gibt eigentlich keinen Unterschied, solange es keine Metaklasse gibt, aber das ist für eine andere Zeit.
Das zweite Problem kommt von der Tatsache, wie eine Funktion tatsächlich in eine Methode umgewandelt wird; Der Funktionstyp implementiert das Deskriptorprotokoll. (See the docs for details.) Kurz gesagt, der Funktionstyp verfügt über eine spezielle -Methode, die aufgerufen wird, wenn Sie eine Attributsuche für die Klasse selbst durchführen. Anstatt das Funktionsobjekt abzurufen, wird die Methode dieses Funktionsobjekts aufgerufen, die ein gebundenes Methodenobjekt zurückgibt (was das Argument self
liefert).
Warum ist das ein Problem? Weil das Objekt functools.partial
kein Deskriptor ist!
>>> import functools
>>> def f(*args):
... print 'f', args
...
>>> g = functools.partial(f, 1, 2, 3)
>>> g
<functools.partial object at 0x10042f2b8>
>>> g.__get__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'functools.partial' object has no attribute '__get__'
Es gibt eine Reihe von Optionen, die Sie an dieser Stelle haben.
import functools
class Foo(object):
def __init__(self):
def f(self, a, b):
print a + b
self.g = functools.partial(f, self, 1)
x = Foo()
x.g(2)
... oder würden Sie die Selbst und den Wert eines in einem Verschluss einzuzubetten: Sie können explizit das Selbst Argument für den Teil liefern
class Foo(object):
def __init__(self):
a = 1
def f(b):
print a + b
self.g = f
x = Foo()
x.g(2)
Diese Lösungen sind natürlich unter der Annahme, dass es ist ein noch unspezifizierter Grund dafür, der Klasse im Konstruktor eine Methode wie diese zuzuordnen, da Sie sehr einfach eine Methode direkt auf der Klasse definieren können, um das zu tun, was Sie hier tun.
Edit: Hier ist eine Idee für eine Lösung, die die Funktionen der Annahme kann für die Klasse erstellt werden, anstelle der Instanz:
class Foo(object):
pass
def make_binding(name):
def f(self, *args):
print 'Do %s with %s given %r.' % (name, self, args)
return f
for name in 'foo', 'bar', 'baz':
setattr(Foo, name, make_binding(name))
f = Foo()
f.foo(1, 2, 3)
f.bar('some input')
f.baz()
Sie gibt:
Do foo with <__main__.Foo object at 0x10053e3d0> given (1, 2, 3).
Do bar with <__main__.Foo object at 0x10053e3d0> given ('some input',).
Do baz with <__main__.Foo object at 0x10053e3d0> given().
Dumm mir, ziemlich offensichtlich im Nachhinein! – pafcu
-1 Da dies eine Problemumgehung ist, aber es ist keine echte Methode - es ist nur eine aufrufbar auf der Instanz gespeichert. Entscheidend ist, dass 'Foo.g' nicht existiert. – wim
@wim OP gibt nicht an, ob g für alle Objekte dieser Klasse gleich sein soll –