Creazione di metodi dinamici in python

1

Ho una classe che avrà un numero di metodi esterni che chiameranno tutti lo stesso insieme più piccolo di metodi interni. Quindi qualcosa del tipo:

obj.method_one (a, c) e obj.method_two (a, c)

dove obj.method_one chiama obj._internal_method (a, c, y) e obj.method_two chiama obj._internal_method (a, c, z).

Sono quasi identici ma hanno un argomento alla fine diverso dalla chiamata interna (che è una costante).

Potrei semplicemente copiare e incollare alcune volte, ma mi stavo chiedendo se esiste un modo per creare dinamicamente questi metodi esterni.

    
posta tonyl7126 18.02.2014 - 03:10
fonte

1 risposta

3

Ci sono modi, ma a meno che tu non ne abbia almeno una mezza dozzina, ti suggerirei:

class myclass(object):
   def _internal_method(self,a,c,y):
       pass # add code here

   def method_one(self,a,c): self._internal_method(a,c,"method one")
   def method_two(self,a,c): self._internal_method(a,c,"another method")

L'altra opzione è di crearla realmente in modo dinamico. Questo può essere fonte di confusione, perché se l'oggetto è ispezionato, i metodi non ci sono. Assomiglia a questo:

class test(object):
    def __getattr__(self,attrname):
        def _internal_method(a,c):
            print "You called %s  with %s and %s" % (attrname,a,c)
        if attrname in ["method_one","method_two"]:
            return _internal_method
        else:
            raise NameError

a=test()
a.method_one("first","second")

Questo fa uso del fatto che ottenere una proprietà (come un metodo) che non esiste, viene chiamata __getattr__ dell'oggetto, e il risultato viene passato indietro. Ricorda che stiamo passando di nuovo la FUNCTION _internal_method come a.method_one , senza chiamarla in questa fase; ciò viene fatto dopo che è stata restituita la chiamata a getattr. Pensa all'ultima riga come:

tmp=a.method
tmp("first","second")

La prima di queste chiamate __getattr__ che restituisce _internal_method (ma non la chiama), quest'ultima chiama _internal_method .

Poiché _internal_method è dichiarato all'interno di __getattr__ , ha lo stesso scope della chiamata che lo ha creato, quindi self e attrname sono accessibili. Inoltre, _internal_method è TRULY privato, non solo "privato per convenzione".

Ribadisco che ciò confonde la prossima persona a mantenere il proprio codice. Ad esempio, se chiedi help(a.method_one) , riceverai invece l'aiuto per _internal_method !

La lunghezza di questa spiegazione e la probabile confusione sono un'ottima ragione per non usarlo a meno che non sia necessario.

    
risposta data 18.02.2014 - 04:21
fonte

Leggi altre domande sui tag