Python中的__getattribute__(或__getattr__)来模拟PHP的__call__
我想创建一个类,能够有效地做到这一点(把一点PHP和Python混合在一起)
class Middle(object) : # self.apply is a function that applies a function to a list # e.g self.apply = [] ... self.apply.append(foobar) def __call(self, name, *args) : self.apply(name, *args)
这样就可以让代码写成:
m = Middle() m.process_foo(a, b, c)
在这个例子中,__call() 是PHP中的一个__call()方法,当在一个对象上找不到某个方法时,它会被调用。
3 个回答
-1
我最近确实做过这个。下面是我解决这个问题的一个例子:
class Example:
def FUNC_1(self, arg):
return arg - 1
def FUNC_2(self, arg):
return arg - 2
def decode(self, func, arg):
try:
exec( "result = self.FUNC_%s(arg)" % (func) )
except AttributeError:
# Call your default method here
result = self.default(arg)
return result
def default(self, arg):
return arg
然后输出结果是:
>>> dude = Example()
>>> print dude.decode(1, 0)
-1
>>> print dude.decode(2, 10)
8
>>> print dude.decode(3, 5)
5
2
考虑一下,把参数直接作为方法的输入,而不是把它们编码在方法名里,然后再神奇地用作参数。
你在哪里写代码时不知道自己会调用哪些方法呢?
为什么要调用 c.do_Something(x)
,然后再从方法名中提取参数,而不直接调用 c.do('Something', x)
呢?
无论如何,处理找不到的属性其实很简单:
class Dispatcher(object):
def __getattr__(self, key):
try:
return object.__getattr__(self, key)
except AttributeError:
return self.dispatch(key)
def default(self, *args, **kw):
print "Assuming default method"
print args, kw
def dispatch(self, key):
print 'Looking for method: %s'%(key,)
return self.default
这是一个测试:
>>> d = Dispatcher()
>>> d.hello()
Looking for method: hello
Assuming default method
() {}
这似乎会有很多“陷阱”——通过 getattr 返回的东西,不仅仅会被认为是一个函数,还会被认为是该实例上的一个绑定方法。所以一定要确保返回的是这个。
3
你需要定义 __getattr__
,这个方法会在你的对象找不到某个属性时被调用。
注意,如果查找失败,就会调用 getattr
,而且你不能像调用普通函数那样直接使用它,所以你需要返回一个将要被调用的方法。
def __getattr__(self, attr):
def default_method(*args):
self.apply(attr, *args)
return default_method