Domanda

Come posso aggiungere un metodo di istanza a una classe utilizzando una metaclasse (sì, devo utilizzare una metaclasse)?Il seguente tipo di lavoro funziona, ma func_name sarà ancora "foo":

def bar(self):
    print "bar"

class MetaFoo(type):
    def __new__(cls, name, bases, dict):
        dict["foobar"] = bar
        return type(name, bases, dict)

class Foo(object):
    __metaclass__ = MetaFoo

>>> f = Foo()
>>> f.foobar()
bar
>>> f.foobar.func_name
'bar'

Il mio problema è che alcuni codici di libreria utilizzano effettivamente func_name e successivamente non riescono a trovare il metodo 'bar' dell'istanza Foo.Potrei fare:

dict["foobar"] = types.FunctionType(bar.func_code, {}, "foobar")

C'è anche Types.MethodType, ma ho bisogno di un'istanza che non esiste ancora per usarlo.Mi sto perdendo qualcosa qui?

È stato utile?

Soluzione

Prova ad estendere dinamicamente le basi in modo da poter sfruttare l'mro e i metodi sono metodi reali:

class Parent(object):
    def bar(self):
        print "bar"

class MetaFoo(type):
    def __new__(cls, name, bases, dict):
        return type(name, (Parent,) + bases, dict)

class Foo(object):
    __metaclass__ = MetaFoo

if __name__ == "__main__":
    f = Foo()
    f.bar()
    print f.bar.func_name

Altri suggerimenti

Penso che quello che vuoi fare è questo:

>>> class Foo():
...   def __init__(self, x):
...     self.x = x
... 
>>> def bar(self):
...   print 'bar:', self.x
... 
>>> bar.func_name = 'foobar'
>>> Foo.foobar = bar
>>> f = Foo(12)
>>> f.foobar()
bar: 12
>>> f.foobar.func_name
'foobar'

Ora sei libero di passare Foos a una biblioteca che si aspetta Foo istanze per avere un metodo denominato foobar.

Sfortunatamente, (1) non so come usare le metaclassi e (2) non sono sicuro di aver letto correttamente la tua domanda, ma spero che questo aiuti.

Notare che func_name è assegnabile solo in Python 2.4 e versioni successive.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top