questa è una cosa che mi è venuta, che si comporterà esattamente come se esiste il metodo.
Prima di tutto stabilire una cosa: non è possibile distinguere se __getattr__
attr
viene da una chiamata di funzione o di un "accesso attributo", perché un metodo di classe è un attributo della classe.Così qualcuno può accedere a tale metodo, anche se non intendono chiamare, come in:
class Test:
def method(self):
print "Hi, I am method"
>> t = Test()
>> t.method # just access the method "as an attribute"
<bound method Test.method of <__main__.Test instance at 0x10a970c68>>
>> t.method() # actually call the method
Hi, I am method
Pertanto, la cosa più vicina che potrei pensare è questo comportamento:
creare una classe A, come ad che:
- Quando proviamo ad accedere a un attributo/metodo, che esiste già in quella classe, comportarsi normalmente e restituire semplicemente l'attributo/metodo richiesto.
- Quando si tenta di accedere a qualcosa che non esiste nella definizione della classe, trattarlo come un metodo di classe e disporre di un gestore globale per tutti questi metodi.
io per prima dare la definizione della classe e poi mostrare come l'accesso a un metodo che non esiste si comporta esattamente come l'accesso a quella che esiste, se sono solo accedervi, o addirittura chiamandolo.
definizione Classe:
class A(object):
def __init__(self):
self.x = 1 # set some attribute
def __getattr__(self,attr):
try:
return super(A, self).__getattr__(attr)
except AttributeError:
return self.__get_global_handler(attr)
def __get_global_handler(self, name):
# Do anything that you need to do before simulating the method call
handler = self.__global_handler
handler.im_func.func_name = name # Change the method's name
return handler
def __global_handler(self, *args, **kwargs):
# Do something with these arguments
print "I am an imaginary method with name %s" % self.__global_handler.im_func.func_name
print "My arguments are: " + str(args)
print "My keyword arguments are: " + str(kwargs)
def real_method(self, *args, **kwargs):
print "I am a method that you actually defined"
print "My name is %s" % self.real_method.im_func.func_name
print "My arguments are: " + str(args)
print "My keyword arguments are: " + str(kwargs)
ho aggiunto il metodo real_method
solo così ho qualcosa che esiste realmente nella classe per confrontare il suo comportamento con quello di un 'metodo di immaginario'
Ecco il risultato:
>> a = A()
>> # First let's try simple access (no method call)
>> a.real_method # The method that is actually defined in the class
<bound method A.real_method of <test.A object at 0x10a9784d0>>
>> a.imaginary_method # Some method that is not defined
<bound method A.imaginary_method of <test.A object at 0x10a9784d0>>
>> # Now let's try to call each of these methods
>> a.real_method(1, 2, x=3, y=4)
I am a method that you actually defined
My name is real_method
My arguments are: (1, 2)
My keyword arguments are: {'y': 4, 'x': 3}
>> a.imaginary_method(1, 2, x=3, y=4)
I am an imaginary method with name imaginary_method
My arguments are: (1, 2)
My keyword arguments are: {'y': 4, 'x': 3}
>> # Now let's try to access the x attribute, just to make sure that 'regular' attribute access works fine as well
>> a.x
1
I metodi non sono gestiti diversamente da altri attributi, è comunque necessario '__getattr__' /' __getattribute__'. – jonrsharpe
@jonrsharpe mmh se implemento una classe A con '__getattr__' e una stampa all'interno e faccio' a = A(); a.foo' stamperà 'foo' ma se chiamo' a = A(); a.foo() 'genererà un' TypeError: 'NoneType' oggetto non è callable' – Salo
'__getattr__' dovrà ancora * restituire * qualcosa richiamabile, non * chiamarlo *, altrimenti si ottiene il valore predefinito' None' – jonrsharpe