在同一实例中使类可调用
class Foo(object):
def tick(self):
print("something")
class Bar(object):
def __init__(self):
self.foo = Foo()
def tick(self):
#Here's what I do....
self.foo.tick()
#here's what my goal would be
self.foo()
b = Bar()
b.tick()
这基本上就是我的目标。从我了解到的情况来看,我可以把tick函数改成__call__
,这样就能实现我想要的功能。有几个其他的回答提到,这样做会创建一个新的对象实例,这是不是意味着它会使用self.foo的内存?还是说会创建一个全新的对象,完全是新的实例?或者是self.foo的一个副本?
另外,我想到了一些可能会出现的缺点。对于我程序中的某个部分,我需要检查这个对象是否有__call__
,以确定我传递的参数是一个函数还是一个变量。我其实不太想让它被调用(尽管我想,从技术上讲,这个类在那时确实会变成一个函数)。有没有什么办法可以区分一个函数和一个可调用的类呢?
还有其他什么原因会让这样做变得不太好(而且这样做算不算是符合Python风格呢)?我接下来想到的是,其他以__
开头的变量不能在类外使用,但在这里似乎并不是这样。
2 个回答
22
要让一个类的实例可以像函数一样被调用,你只需要实现一个叫做 __call__
的方法。然后,要调用这个 __call__
方法,你只需这样做: instance(arg1,arg2,...)
—— 换句话说,你可以像调用函数一样调用这个实例。
需要注意的是,如果你愿意,可以用类中定义的其他方法来替代 __call__
的名字:
>>> class Foo(object):
... def tick(self):
... print ("something")
... __call__ = tick
...
>>> a = Foo()
>>> a()
something
>>> a.tick()
something
31
把 tick(self)
改成 __call__(self)
是正确的做法。
这和内存分配没有关系。__call__
的意思是,当你用一个对象 foo
这样调用它:foo()
时,Python 会调用的那个函数。
关于你后面的问题:要检查某个东西是不是对象,可以用 isinstance
或者 issubclass
(可能还要用到 object
类)。在我看来,这个回答 比你可能见过的关于“我怎么判断某个东西是不是函数?”的问题的接受回答要好。