【问题标题】:How to distinguish default argument and argument provided with default value?如何区分默认参数和提供默认值的参数?
【发布时间】:2021-04-21 19:27:53
【问题描述】:

假设我有函数f如下:

def f(c=None):
    return 42 if c is None else c

那么我无法从这个函数中得到None。现在您可能会想“好吧,只需检查另一个值,例如 2128.213 或其他值”,但我无法从函数中获取该特定值,可以吗?

这就是为什么我想在可能的情况下区分 f()f(None) 以便我可以拥有

f() -> 42
f(None)-> None

请记住,这是一个简化的示例。在实践中,它是一个类的 __init__(...) 函数,具有多个位置参数,在本例中我想将其处理为 c

【问题讨论】:

  • 为什么你需要知道 None 来自这里还是那里?你想达到什么目的?
  • 如果f()f(None) 相比,您想做什么不同的事情?
  • 不正确的逻辑即使你的 c 没有你仍然会得到 42
  • 等等,你想区分定义中的 None 和用户传递的 None 吗?
  • 使用类似_DEFAULT = object()的默认值,在同一个模块中定义 - 没有其他模块可以传递与此相同的值。

标签: python default-arguments


【解决方案1】:

这种情况下的常见做法是使用您永远不想返回的特定标记值。

class Sentinel():
    pass


_sentinel = Sentinel()

# _sentinel = object()  # this is the option too

def f(x=_sentinel):
    return 42 if x is _sentinel else x

assert f() == 42
assert f(None) is None
assert f(5) == 5

【讨论】:

  • @wjandrea somemodule.f(somemodule._sentinel) == somemodule._sentinel,这就是问题所在
  • @Programmer 没有人应该使用somemodule._sentinel,因为前导下划线表示它仅供内部使用。当然,这仍然是可能的,因为 Python 没有真正的私有变量,但强烈建议不要这样做。
  • @Programmer 这仍然不是真正的私有,只是被混淆了。有关说明,请参阅 this answer。 TL;DR cls._cls__attr 是混淆名称。
  • @Programmer 从未听说过名称修改?
  • @Programmer 您可以使用cls._cls__attr访问它。请参阅我链接的答案以获得解释,以及What is the meaning of single and double underscore before an object name?
【解决方案2】:

您可以利用 Python 的私有属性:为该私有属性分配一个新对象,比较参数是否为私有对象,然后完成。

class somename:
    __default = object()
    def __init__(self, default=__default):
        print(42 if default is self.__default else default)

somename()
somename(default=12)

【讨论】:

  • 我经常将其命名为 NULL 表示“没有指定”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
相关资源
最近更新 更多