這是我想出來的東西,它的行爲就好像存在方法一樣。
首先,我們建立了一兩件事:你不能在__getattr__
區分,如果attr
來自函數調用或「屬性訪問」,因爲類方法是你的類的屬性。因此,有人可以訪問方法,即使他們不打算叫它,如:
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
因此,我能想到的最接近的是這種行爲:
創建A級,這樣的即:
- 當我們嘗試訪問已存在於該類中的屬性/方法時,將正常運行並返回請求的屬性/方法。
- 當我們嘗試訪問類定義中不存在的東西時,將其視爲一個類方法,並對所有這些方法都有1個全局處理程序。
我將首先編寫類定義,然後說明如何訪問不存在的方法的行爲與訪問存在的方法完全相同,無論您是隻是訪問它,還是實際調用它。
類定義:
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)
我添加的方法real_method
只是讓我有一個真正的類存在與一個「虛方法」
這裏來比較其行爲的東西,結果如下:
>> 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
方法是無異於任何其他屬性,你仍然需要'__getattr__' /'__getattribute__'處理。 – jonrsharpe
@jonrsharpe mmh如果我用'__getattr__'實現一個類A並在裏面打印並且執行'a = A(); a.foo'會打印'foo',但如果我打電話'a = A(); a.foo()'它會引發一個'TypeError:'NoneType'對象不可調用' – Salo
'__getattr__'仍然必須*返回*可調用的東西,而不是*調用*它,否則返回默認的'None' – jonrsharpe