在python中,是否有某种映射返回类型的"假值"?

Mat*_*ttS 42 python types boolean

我正在寻找f()某种类似于此的映射函数:

f(str) = ''
f(complex) = 0j
f(list) = []
Run Code Online (Sandbox Code Playgroud)

这意味着它返回一个类型的对象,该对象在转换为时被计算Falsebool.

这样的功能存在吗?

Ara*_*Fey 66

不,没有这样的映射.并非每种类型的对象都具有虚假价值,而其他对象则具有多种价值.由于可以使用该__bool__方法自定义类的真值,因此理论上类可以具有无限数量的(不同的)虚假实例.

也就是说,大多数内置类型在没有参数的情况下调用构造函数时会返回其伪值:

>>> str()
''
>>> complex()
0j
>>> list()
[]
Run Code Online (Sandbox Code Playgroud)

  • "理论上,一个类在理论上可以有无数个(不同的)假实例"或者为零. (10认同)
  • @RemcoGerlich:你忘了测试`object()`,这是真的.如果计算异常,我相信所有内置的异常类型在没有参数的情况下调用时返回一个真正的对象.一些技术类型但通常不被视为类型的内置函数也返回truthy值,如`property()`或`zip()`. (8认同)
  • 这适用于https://docs.python.org/3/library/stdtypes.html中令人惊讶的许多类型; `type()`,`range()`和`memoryview()`因为期望参数而失败并带有`TypeError`.其他类型如模块和类可能不太相关.据我所知,这永远不会为任何内置类型返回真值. (3认同)

jua*_*aga 26

不,一般来说,可能没有这样的价值.关于如何实现类型的真值,Python 数据模型非常松散:

object.__bool__(self)

被称为实施真值测试和内置操作bool(); 应该返回False或True.如果未定义此方法,__len__()则调用此方法( 如果已定义),如果其结果为非零,则将该对象视为true.如果一个类既未定义也__len__() 未定义__bool__(),则其所有实例都被视为真.

所以考虑:

import random
class Wacky:
    def __bool__(self):
        return bool(random.randint(0,1))
Run Code Online (Sandbox Code Playgroud)

应该f(Wacky)返回什么?

  • 或[__nonzero__](https://docs.python.org/2/reference/datamodel.html#object.__nonzero__)for python 2 (6认同)

Kar*_*ldt 6

实际上,这称为标识元素,在编程中,通常将其视为monoid定义的一部分。在python中,您可以使用PyMonad包中的mzero函数将其获取为一种类型。Haskell称它为无礼


Mad*_*ist 5

并非所有类型都具有这样的价值.其他人可能有很多这样的价值.这样做的最正确的方法是创建一个类型到值的dict,因为那样你可以检查一个给定的类型是否在dict中,如果有多个选项你可以选择哪个值是正确的.缺点当然是您必须以某种方式注册您感兴趣的每种类型.

或者,您可以使用一些启发式编写函数.如果你对你传递给函数的内容非常小心,它可能会有一些限制.例如,您显示的所有情况除外complex是用于概括的容器cls().

complex实际上也是这样的,但我单独提到它,因为intfloat没有.因此,如果您尝试使用空构造函数失败,则返回一个真实的对象或者提升一个TypeError,您可以尝试cls(0).等等等等...

更新

@ juanpa.arrivillaga的答案实际上暗示了一个适用于大多数课程的聪明的解决方法.您可以扩展该类并强制创建一个假实例但与原始类相同的实例.你必须通过扩展来做到这一点,因为类似的dunder方法__bool__只能在类上查找,而不是在实例上查找.还有许多类型,这些方法无法在实例上替换.正如@ Aran-Fey现在删除的评论指出的那样,你可以选择性地打电话,object.__new__或者t.__new__,根据你是否正在处理一个非常特殊的情况(如int):

def f(t):
    class tx(t):
        def __bool__(self):
            return False
    try:
        return object.__new__(tx)
    except TypeError:
        return tx.__new__(tx)
Run Code Online (Sandbox Code Playgroud)

这只适用于您遇到的99.9%的课程.有可能创建一个人为的案例,TypeError当它传递给object.__new__as时int,并且不允许没有arg版本t.__new__,但我怀疑你会在自然界中找到这样的东西.请参阅@ Aran-Fey 的要点来证明这一点.