如何使可选参数成为必需的?

2024-10-03 04:40:08 发布

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

基于Disable global variable lookup in Python(以及我自己的答案),我在使用带有可选参数的函数时遇到了问题,例如在下面这个最小的示例中:

import types

def noglobal(f):
    return types.FunctionType(f.__code__, {})

@noglobal
def myFunction(x=0):
    pass

myFunction()

基本上,它是这样失败的:

Traceback (most recent call last):
  File "SetTagValue.py", line 10, in <module>
    myFunction()
TypeError: myFunction() missing 1 required positional argument: 'x'

为什么x突然被视为必需的参数?你知道吗


Tags: 函数答案inimport示例参数returndef
2条回答

这是因为你没有正确地复制函数。如果您查看types.FunctionType的签名,您将看到它接受5个参数:

class function(object)
 |  function(code, globals, name=None, argdefs=None, closure=None)
 |
 |  Create a function object.
 |
 |  code
 |    a code object
 |  globals
 |    the globals dictionary
 |  name
 |    a string that overrides the name from the code object
 |  argdefs
 |    a tuple that specifies the default argument values
 |  closure
 |    a tuple that supplies the bindings for free variables

您没有传递任何argdefs,因此函数不再具有可选参数。复制函数的正确方法是

types.FunctionType(f.__code__,
                   {},
                   f.__name__,
                   f.__defaults__,
                   f.__closure__
                   )

然而,这导致了另一个问题:切断对globals的访问也切断了对内置的访问。如果您尝试使用printopendict或类似的myFunction,您将得到NameError。因此,编写decorator的正确方法是:

import builtins
import types

def noglobal(f):
    return types.FunctionType(f.__code__,
                              {'__builtins__': builtins},
                              f.__name__,
                              f.__defaults__,
                              f.__closure__
                              )

如果要保留默认参数值,还需要传递它们:

import types

def noglobal(f):
    return types.FunctionType(f.__code__, {}, f.__name__, f.__defaults__)

@noglobal
def myFunction(x=0):
    pass

myFunction()

您可以将最后一个closure参数传递给types.FunctionType,如果您想让闭包的函数继续工作,您可能还希望从f.__closure__继承该参数。你知道吗

相关问题 更多 >