如何在Python中实现Dog()()()()()()

88 阅读2分钟

**如何在Python中实现Dog()()()()()() **

Dog后面跟着无限个()

image.png

如何编写一个类,使以下代码能够运行?

Dog()
Dog()()
Dog()()()()()
Dog()()()()()()()()()()

^ 我们希望我们的代码能够运行,无论我们在后面添加多少个()。

class Dog:
  pass
print(Dog()) # <__main__.Dog object at 0x1043dbe60>

当我们在Dog类后面添加()时,我们初始化了一个Dog类型的对象。

class Dog:
  def __call__(self):
    return 'hello!!'
print(Dog())    # <__main__.Dog object at 0x1043dbe60>
print(Dog()())  # hello!!

^ 在这里,__call__魔法方法定义了我们调用Dog对象时的行为。

我们简单地告诉__call__返回一个字符串。因此,如果我们有一个Dog对象Dog(),并像函数一样调用它Dog()(),我们将得到一个字符串。

class Dog:
  def __call__(self):
    return 'hello!!'
print(Dog())      # <__main__.Dog object at 0x1043dbe60>
print(Dog()())    # hello!!
print(Dog()()())  # ERROR

^ 然而,如果我们执行Dog()()(),我们是在像函数一样调用一个字符串,因为Dog()()返回一个字符串。因此,我们会得到一个错误。所以我们不能让__call__返回一个字符串。

class Dog:
  def __call__(self):
    return Dog
print(Dog())      # <__main__.Dog object at 0x1043dbe60>
print(Dog()())    # <class '__main__.Dog'>
print(Dog()()())  # <__main__.Dog object at 0x1043dbe60>

^ 在这里,我们让__call__返回一个Dog对象本身。

  • Dog() → 一个Dog对象
  • Dog()() → Dog类
  • Dog()()() → 再次一个Dog对象
class Dog:
  def __call__(self):
    return Dog
print(Dog())          # <__main__.Dog object at 0x1043dbe60>
print(Dog()())        # <class '__main__.Dog'>
print(Dog()()())      # <__main__.Dog object at 0x1043dbe60>
print(Dog()()()())    # <class '__main__.Dog'>
print(Dog()()()()())  # <__main__.Dog object at 0x1043dbe60>

^ 注意,每当我们在后面添加一个额外的()时,我们在Dog类和Dog对象之间交替。

这意味着由于我们的特殊__call__魔法方法,我们现在可以在Dog后面有无限个()。

__call__ 是 Python 中的一个特殊方法,使得一个对象可以像函数一样被调用。当你在一个对象上使用括号 () 时,实际上是在调用该对象的 __call__ 方法。

下面介绍一下__call__

call 方法

通过定义 __call__ 方法,你可以自定义对象在被调用时的行为。这使得对象可以作为函数使用,增强了灵活性。

示例

class MyClass:
    def __call__(self, x):
        return x * 2

obj = MyClass()
print(obj(5))  # 输出: 10

在这个例子中,MyClass 的实例 obj 可以像函数一样被调用,传入参数 5,并返回 10