使类在同一实例中可调用

Posted

技术标签:

【中文标题】使类在同一实例中可调用【英文标题】:making a class callable in same instance 【发布时间】:2013-01-13 04:55:42 【问题描述】:
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()

这基本上就是我的目标。根据我收集到的信息,我可以将刻度函数更改为__call__,这样我就可以做我想做的事了。其他几个答案说这将创建一个对象的新实例,这是否意味着它将使用 self.foo 的内存?还是会创建一个全新的对象,新实例化?或者复制一份 self.foo?

我还想到了一些可能会或可能不会表现出来的缺点。对于我程序的特定部分,我检查对象是否有 __call__ 以确定我传递的参数是函数还是变量,我真的不认为我会允许它被调用(即使,我认为该类在技术上将是一个函数。)有没有办法区分函数和可调用类?

还有什么东西会让这样做不受欢迎(这是一种 Python 的工作方式吗?)?我的下一个想法是,考虑到其他以__ 为前缀的变量不能在他们的班级之外使用,但这里似乎并非如此。

【问题讨论】:

实现__call__不会创建对象的新实例。执行TheClass() 会创建一个新实例,但some_instance() 只是调用__call__ 我只是在你没有想到的情况下提到这一点 -- 但是,使用上面非常简单的代码,让 Bar 继承自 Foo 似乎是一个不错的选择-- 当然,您的用例可能不是一个好选择... 【参考方案1】:

tick(self) 更改为__call__(self) 是正确的解决方案。

这与内存分配无关。所有__call__ 表示的是当您使用(对于对象foo)语法foo() 时Python 调用的函数。

对于您后面的问题:要检查某物是否是对象,请使用 isinstanceissubclass(可能与 object 类一起使用)。在我看来,this answer 比公认的“我如何确定某物是否是函数?”更好。你可能见过的问题。

【讨论】:

【参考方案2】:

要使类实例可调用,您需要做的就是实现__call__ 方法。然后,要调用__call__ 方法,您只需:instance(arg1,arg2,...)——换句话说,您调用实例的方式与调用函数的方式相同。

请注意,如果需要,您可以使用在类上定义的其他方法为 __call__ 起别名:

>>> class Foo(object):
...     def tick(self):
...         print ("something")
...     __call__ = tick
... 
>>> a = Foo()
>>> a()
something
>>> a.tick()
something

【讨论】:

如果你要实现一个带参数的函数,你还能使用这种别名方法吗?还是仅在函数只有一个参数时才起作用self 我正在努力让不同的实例有不同的 call 方法。但是,如果我在 init__() 中设置 self.__call__,当我实际调用 instance() 时,我会得到 TypeError: 'CallableClass' object is not callable。有没有办法以不同的方式设置 __call 实例到实例? 您可以拥有一个_delegate 属性,__call__ 将委托给:def __call__(self): self._delegate()

以上是关于使类在同一实例中可调用的主要内容,如果未能解决你的问题,请参考以下文章

callable函数,检查对象是否可调用

任何 spritesheet 的可调用 spritesheet 类

设计模式之单例模式

单例模式(Singleton)

防止类在 Python 中直接实例化

可调用实例参数的表示法是啥?