这是我想出来的东西,它的行为就好像存在方法一样。
首先,我们建立了一两件事:你不能在__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