简体   繁体   English

什么时候使用__call__好主意?

[英]When is using __call__ a good idea?

What are peoples' opinions on using the __call__ . 人们对使用__call__的看法是什么。 I've only very rarely seen it used, but I think it's a very handy tool to use when you know that a class is going to be used for some default behaviour. 我只是很少看到它使用,但我认为当你知道一个类将被用于某些默认行为时,它是一个非常方便的工具。

I think your intuition is about right. 我认为你的直觉是正确的。

Historically, callable objects (or what I've sometimes heard called "functors") have been used in the OO world to simulate closures. 从历史上看,OO世界中使用了可调用对象(或者我有时称之为“仿函数”的对象)来模拟闭包。 In C++ they're frequently indispensable. 在C ++中,它们经常是不可或缺的。

However, __call__ has quite a bit of competition in the Python world: 但是, __call__在Python世界中有相当多的竞争:

  • A regular named method, whose behavior can sometimes be a lot more easily deduced from the name. 一种常规命名方法,其行为有时可以更容易地从名称中推断出来。 Can convert to a bound method, which can be called like a function. 可以转换为绑定方法,可以像函数一样调用。
  • A closure, obtained by returning a function that's defined in a nested block. 一个闭包,通过返回嵌套块中定义的函数获得。
  • A lambda, which is a limited but quick way of making a closure. 一种lambda,这是一种有限但快速的封闭方式。
  • Generators and coroutines, whose bodies hold accumulated state much like a functor can. 生成器和协同程序,其身体保持积累状态就像仿函数一样。

I'd say the time to use __call__ is when you're not better served by one of the options above. 我会说使用__call__的时间是因为上面的一个选项没有给你更好的服务。 Check the following criteria, perhaps: 或许,请检查以下标准:

  • Your object has state. 你的对象有状态。
  • There is a clear "primary" behavior for your class that's kind of silly to name. 你的班级有明确的“主要”行为,这有点愚蠢。 Eg if you find yourself writing run() or doStuff() or go() or the ever-popular and ever-redundant doRun() , you may have a candidate. 例如,如果您发现自己编写run()doStuff()go()或者流行且永远冗余的doRun() ,您可能会有候选人。
  • Your object has state that exceeds what would be expected of a generator function. 您的对象的状态超出了生成器函数的预期。
  • Your object wraps, emulates, or abstracts the concept of a function. 您的对象包装,模拟或抽象函数的概念。
  • Your object has other auxilliary methods that conceptually belong with your primary behavior. 您的对象具有其他辅助方法,这些方法在概念上属于您的主要行为。

One example I like is UI command objects. 我喜欢的一个例子是UI命令对象。 Designed so that their primary task is to execute the comnand, but with extra methods to control their display as a menu item, for example, this seems to me to be the sort of thing you'd still want a callable object for. 设计的目的是让他们的主要任务是执行comnand,但是使用额外的方法来控制他们的显示作为菜单项,例如,在我看来,这仍然是你仍然想要一个可调用对象的东西。

Use it if you need your objects to be callable, that's what it's there for 如果您需要对象可以调用,请使用它,这就是它的用途

I'm not sure what you mean by default behaviour 我不确定你的默认行为是什么意思

One place I have found it particularly useful is when using a wrapper or somesuch where the object is called deep inside some framework/library. 我发现它特别有用的一个地方是使用包装器或某些框架/库内深度调用对象的地方。

More generally, Python has a lot of double-underscore methods. 更一般地说,Python有很多双下划线方法。 They're there for a reason: they are the Python way of overloading operators. 它们存在的原因是:它们是重载运算符的Python方式。 For instance, if you want a new class in which addition, I don't know, prints "foo" , you define the __add__ and __radd__ methods. 例如,如果你想要一个新的类,我不知道,打印"foo" ,你可以定义__add____radd__方法。 There's nothing inherently good or bad about this, any more than there's anything good or bad about using for loops. 关于这一点没有任何本质上的好或坏,除了使用for循环有任何好处或坏处之外。

In fact, using __call__ is often the more Pythonic approach, because it encourages clarity of code. 事实上,使用__call__通常是更多Pythonic方法,因为它鼓励代码清晰。 You could replace MyCalculator.calculateValues( foo ) with MyCalculator( foo ) , say. 你可以取代MyCalculator.calculateValues( foo )MyCalculator( foo ) ,说。

Its usually used when class is used as function with some instance context, like some DecoratorClass which would be used as @DecoratorClass('some param') , so 'some param' would be stored in the instance's namespace and then instance being called as actual decorator. 它通常在类被用作具有某些实例上下文的函数时使用,例如一些将用作@DecoratorClass('some param') DecoratorClass,因此'some param'将存储在实例的命名空间中,然后实例被称为实际装饰。

It is not very useful when your class provides some different methods, since its usually not obvious what would the call do, and explicit is better than implicit in these cases. 当你的类提供一些不同的方法时它并不是很有用,因为它通常不明显调用会做什么,而在这些情况下,显式优于隐式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM