有什么方法可以知道参数的值是默认值还是用户指定的值?

问题描述 投票:0回答:5

我正在寻找像 Lisp 的 arg-supplied-p 变量一样工作的东西,以帮助区分默认值和用户指定的相同值。

示例:

def foo(a=10):
    pass

我想知道 foo 中是否是这样调用的:

foo()

或者像这样:

foo(10)

甚至像这样:

foo(a=10)

最后两个对我来说足够同义;我不需要知道那个细节。我稍微浏览了一下检查模块,但是 getargspec 对于所有 3 个调用返回完全相同的结果。

python arguments
5个回答
12
投票

除了检查源代码之外,没有办法区分这三个函数调用——它们“意味着”具有完全相同的含义。如果您需要区分它们,请使用不同的默认值,例如None


def foo(a=None): if a is None: a = 10 # no value for a provided



7
投票

sentinel = object() def foo(a=sentinel): if a is sentinel: # No argument was provided ...



2
投票
foo.func_defaults

获取函数默认参数的列表,因此您可以使用它来检查传递参数的对象标识。但这仅适用于可变对象。正如您的示例所示,无法判断某人是否通过了 10 还是使用了默认的 10,因为这两个 10 很可能是同一个对象。


无论如何,这只是一个粗略的近似值,因为它没有告诉您该函数是如何调用的:它告诉您默认参数是什么,然后您查看实际参数,并尝试猜测它们是否相同。无法访问用于调用该函数的语法形式。

这里有一个示例,展示了它有时有效、有时无效的情况。

>>> def f(x="this is crazy"): ... print x is f.func_defaults[0] >>> f() True >>> f("this is crazy") False >>> def f(x=10): ... print x is f.func_defaults[0] >>> f() True >>> f(10) True



0
投票
他们可以'不准进去。

他们可以传入

None

,所以你不能使用它。你能用什么?


最简单的解决方案是创建某种Python对象,将其用作函数中的默认值,然后

del

这样用户就无法引用它。从技术上讲,用户可以从你的函数对象中挖掘出这一点,但他们很少会这样做,如果他们这样做,你可以说他们应得的。


default = [] def foo(a=default): if a is default: a = 10 print a del default

我在这里使用的“默认值”是一个空列表。由于列表是可变的,因此它们永远不会被重用,这意味着每个空列表都是一个唯一的对象。 (Python 实际上对所有空元组使用相同的空元组对象,所以不要使用空元组!字符串文字和小整数类似地重用,所以也不要使用它们。) 
object

实例就可以了。任何东西,只要它是可变的,因此就不会被共享。


现在的问题是上面的代码实际上不会运行,因为你已经完成了

del default

。如何在运行时在函数中获取对此对象的引用,以便可以对其进行测试?一种方法是使用默认参数值,该值不用于实际参数。


default = [] def foo(a=default, default=default): if a is default: a = 10 print a del default

这会在定义函数时将对象绑定到参数的默认值,因此一秒钟后删除全局名称并不重要。但问题是,如果有人对你的函数做了
help()

,或者以其他方式反思它,看起来他们可以传入一个额外的参数。更好的解决方案是闭包:


default = [] def foo(default=default): # binds default to outer func's local var default def foo(a=default): # refers to outer func's local var default if a is default: a = 10 print a return foo foo = foo() del default

这需要做很多工作,所以真的,不用费心。


0
投票

None

 默认与用户指定。
自 2021 年起,

PEP 661

告诉我们使用 Sentinel 类:

from sentinels import Sentinel

NotGiven = Sentinel('NotGiven')

def foo(a=NotGiven):
    if a is NotGiven:
        # No argument was provided
        ...

© www.soinside.com 2019 - 2024. All rights reserved.