【问题标题】:Python - What does it mean to return a function object?Python - 返回一个函数对象是什么意思?
【发布时间】:2020-04-16 22:31:46
【问题描述】:

我正在尝试了解 Python 中的装饰器。我已经从 SO: 上的各种答案 [ex] 中了解了它们的用途:在修饰函数之前和/或之后运行代码而不修改函数本身。也就是说,我无法理解返回函数对象的含义。

返回函数的返回值和返回函数对象有什么区别?我知道返回了对函数本身的引用,但是这种行为的用处是什么?

我没有使用下面的 @Decorator 语法,因为我还在学习。

例如:

def some_func():
    print('returning 1')
    return 1
def Decorator(func):
    def Wrapper():
        print('doing something first')
        val = func()
        print('doing something after')
        return val
    return Wrapper
Decorated_func = Decorator(some_func)
Decorated_func()

在 PythonTutor 中单步执行:调用 Decorated_func() 表明 Wrapper 的返回值为 1Decorator 的返回值为 Wrapper。这是否意味着Decorator 实际上 在调用Decorated_func() 时返回值为1?我原以为该行为的语法是(在Decorator 内)return Wrapper()。返回函数对象有什么意义?

【问题讨论】:

  • 函数只是一个对象,就像一个列表或一个整数。它与从函数返回任何其他对象的目的相同。
  • 看来你真的在问“为什么高阶函数有用?”
  • 如果你返回 Wrapper() 然后 Decorated_func == 1 并且它不会是一个函数......尝试这样做,然后看看当你尝试使用 Decorated_func 作为函数时会发生什么
  • @Brian 是的,OP 甚至提供了一个有用的例子。
  • no,这 不意味着 Decorator 实际上的返回值是 1,返回值是您在 Decorator 中创建的包装函数

标签: python oop decorator


【解决方案1】:

当你返回一个函数时,调用者可以用不同的参数多次调用它,每次都可以计算出不同的结果。

如果你返回调用函数的结果,你只是返回一个值,它永远不会改变。而且由于它不是函数,所以不能使用不同的参数调用它。

这是一个更简单的例子:

def adder(x):
    def add_x(y):
        return x + y
    return add_x

add_1 = adder(1)
add_3 = adder(3)
print(add_1(10)) # prints 11
print(add_1(20)) # prints 21
print(add_3(10)) # prints 13

如果您将其更改为 return add_x(5) 之类的内容,那么 adder(1) 将仅返回 6,而不是您可以使用不同参数调用的函数。

【讨论】:

    【解决方案2】:

    首先,让我们澄清一下您提出的很好的、重点突出的问题:

    这是否意味着当 Decorated_func() 被调用时,Decorator 实际上的返回值为 1?

    没有。 Decorator 是一个配置工具。你给它一个函数对象。 Decorator 将该函数对象插入其隐藏模板 (Wrapper),然后将自定义的 Wrapper 作为新函数返回。那个自定义函数就是Decorator的返回值。

    调用该包装器不会改变Decorator 的操作方式。请注意,这不是Decorator 的调用。 Decorator 制作了一个自定义版本的包装器——that 的值为 1Decorator 还是原来的自己,一个定制工厂,等待别人插入一些其他的功能。

    【讨论】:

      【解决方案3】:

      返回一个函数可以让您“分两步调用”。例如,您可以从同一个基本函数创建任意数量的函数。

      def testDecorator(x):
          print(f'I am {x}')
          return x * 2
      
      def printA(func):
          def wrapper(x):
             print('I am the decorator A opening')
             result = func(x)
             print('I am the decorator A ending')
             return result
          return wrapper
      
      def printB(func):
          def wrapper(x):
             print('I am the decorator B opening')
             result = func(x)
             print('I am the decorator B ending')
             return result
          return wrapper
      
      testA = printA(testDecorator)
      testB = printB(testDecorator)
      
      >>> testA(5)
      I am the decorator A opening
      I am 5
      I am the decorator A ending
      10
      >>> testB(5)
      I am the decorator B opening
      I am 5
      I am the decorator B ending
      10
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多