Python中的等同函数机制

2024-04-19 17:19:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我了解到,在Python中,我们可以将一个函数与另一个函数等同起来,如下所示:

def func_1(x)
    print("func_1")
    print(x)

def func_2(x)
    print("func_2")
    print(x)

func_1 =func_2

所以这里发生的是,对func\u1的每次调用都执行func\u2。你知道吗

然而,我读到了关于decorators的内容,下面是一个简单的代码来说明它们:

def our_decorator(func):
    def function_wrapper(x):
        print("Before calling " + func.__name__)
        func(x)
        print("After calling " + func.__name__)
    return function_wrapper

def foo(x):
    print("Hi, foo has been called with " + str(x))

print("We call foo before decoration:")
foo("Hi")

print("We now decorate foo with f:")
foo = our_decorator(foo)

print("We call foo after decoration:")
foo(42)

我们可以在下面一行看到:

foo = our_decorator(foo)

类似于上一个函数方程的事情正在发生。我认为这就是decorator的工作方式,也就是说,将对decorator的调用替换为对decorator的调用。你知道吗

然而,在这种印象下,如果我写一个代码如下:

def our_decorator():
    def function_wrapper(x):
        print("Before calling " )
        foo(x)
        print("After calling " )
    return function_wrapper

def foo(x):
    print("Hi, foo has been called with " + str(x))

print("We call foo before decoration:")
foo("Hi")

print("We now decorate foo with f:")
foo = our_decorator()

print("We call foo after decoration:")
foo(42)

上述结果导致无限递归打印无限个“调用前”。你知道吗

所以,我可以得出结论,装饰器必须是以函数为参数的东西。你知道吗

所以函数的等价在这两个cae中是不同的,即等价于以另一个函数为参数的函数,和等价于不以另一个函数为参数的函数。你知道吗

这两者在内部实现上有什么不同?你知道吗


Tags: 函数foodefwithourfunctiondecoratorcall
3条回答

装饰师看起来是这样的:

def decorator_with_args(*args, **kwargs):
    def wrapper(f: "the function being decorated"):
        def wrapped(*args, **kwargs):
            # inside here is the code that is actually executed
            # when calling the decorated function. This should
            # always include...
            f(*args, **kwargs)

            # and usually return its result
        return wrapped
    return wrapper

# or

def decorator_without_args(f: "the function being decorated"):
    def wrapped(*args, **kwargs):
        # as above
        return f(*args, **kwargs)
    return wrapped

用于:

@decorator_with_args("some", "args")
def foo(x):
    print("foo:", x)  # or whatever

@decorator_without_args
def bar(x):
    print("bar:", x)

这相当于在没有@decorator...魔力的情况下定义每个函数,然后应用decorator

def baz(x):
    print("baz:", x)

baz = decorator_with_args("some", "arguments")(baz)
# or
baz = decorator_without_args(baz)

在示例代码中,您在decorator内调用foo,然后使用该decorator对foo进行修饰,因此最终会无限递归。每次调用foo时,它都会运行装饰程序代码,该代码也会调用foo。每次您的decorator调用foo,它都会运行您的decorator代码,该代码也会调用foo。每次您的decorator的decorator调用foo,is都会运行您的decorator代码,该代码还。。。等等

我希望你的问题能通过解释几个术语来回答。你知道吗

  1. 您使用术语“相等”来表示通常所说的“分配”。name = expr是赋值语句。名称name被赋予(赋值)作为表达式expr的结果的对象。

  2. 在Python中,函数不是特殊的。这有时用一句话来表达,即“函数是第一类对象”,这基本上意味着函数对象可以赋值给变量(名称),作为参数传递,与数字、字符串和其他对象的方式相同。

  3. (函数)修饰器处理另一个函数。它是一个函数,将要修饰的函数作为它的参数,并返回它的“修饰”(即以某种方式增强或修改)版本。有时它只将函数注册为处理程序或API的一部分,并返回不变的函数。它有一个特殊的语法:

你知道吗

@decorator
def func(...):
    pass

相当于:

func = decorator(func)

还有:

@decorator(args)
def func(...):
    pass

相当于:

_real_decorator = decorator(args)
func = _real_decorator(func)

因为这种@decorator语法非常易于使用和阅读,您通常不会编写:

func = decorator(func)

总结一下:

func1 = some_func是普通赋值,给some_func起了另一个名字。你知道吗

func2 = create_function()这在某些语言中称为函数工厂。你在问题里写的。你知道吗

func = decorate_function(func)这是func的装饰

注意:存在类装饰器,它们非常相似,但是增强了类定义而不是函数。你知道吗

你所谓的“等值函数”其实只是一个变量赋值。函数定义(使用def)创建函数并将其分配给变量名。执行func_1 = func_2之后,有两个变量引用同一个函数。你知道吗

在您的decorator示例中发生的事情是前一段的自然结果。如果你需要进一步的澄清,请留下评论。你知道吗

相关问题 更多 >