dict.get(None) 在具有 None 值的 dict 上采用默认 arg

如何解决dict.get(None) 在具有 None 值的 dict 上采用默认 arg

我试图概括这种情况:

def func(t):
    # code which doesn't accept None's

def foo(a):
    if a in ('',None):
        return None
    return func(a)

def foo_b(a):
    if a in ('',None):
        return None
    elif a == 'b'
         return 0
    return func(a)

我试图解决它的方法是定义一个字典:

defaults = {None: None,'': None}

def foo(a):
    return defaults.get(a,func(a))

def foo_b(a):
    defaults_b = {'bar': 0,**defaults}
    return defaults_b.get(a,func(a))

运行脚本时:

foo_b(None)

它进入 get 方法, 从 None 字典取回 defaults 并使用 func() 进入 None 方法 我得到错误原因 func() 方法不排除 None

用python解决这个问题的最佳实践是什么?

解决方法

这行不通,因为函数的所有参数在调用函数之前都已计算。所以当你写

defaults.get(a,func(a))

它首先计算 afunc(a),并将这两个结果传递给 defaults.get()。由于 func(a) 不适用于某些 a 值,因此在进入 defaults.get() 之前您会收到错误消息。

解决这个问题的一般方法是默认为一个函数,只有在必要时才会调用。您需要编写自己的 dict.get() 版本,以这种方式工作。

def dict_get_f(d,key,default_fun):
    if key in d:
        return d[key]
    return default_fun()

然后你可以像这样使用它:

def foo(a):
    return dict_get_f(defaults,a,lambda: func(a))
,

为什么不直接检查函数本身?

def func(t):
    if t is None:
        return None
    # go on with the code

    
,

问题

正如@Barmar 在他们的回答中指出的那样,问题不在于 dict.get 的行为,而是在调用函数之前评估所有参数的事实,因此 defaults.get(a,func(a)) 调用 {{1} } 在使用该值调用 func(a) 之前。

解决方案 1:defaults.get

解决此问题的另一种方法是使用 collections.defaultdict,它提供了一种在值不在字典中时调用函数的方法。

因为你的字典很小,复制它们的成本很低,所以这个解决方案可以做到这一点。

collections.defaultdict

解决方案 2:无处不在的函数!

您可以采用的另一种方法是将 from collections import defaultdict defaults = {None: None,'': None} def func(arg): """Some function that cannot be called with None""" if arg is None: raise ValueError() print(f'func called with {arg}') def foo(a): return defaultdict(lambda: func(a),defaults)[a] def foo_b(a): defaults_b = {'bar': 0,**defaults} return defaultdict(lambda: func(a),defaults_b)[a] if __name__ == '__main__': print(foo(None)) print(foo('')) print(foo(123)) print(foo(123)) print(foo_b(None)) print(foo_b('bar')) 字典设为函数字典,并使用默认值 defaults,以避免使用 lambda: func(a) 调用函数。因此,None 将返回一个返回正确值的函数,然后您可以调用该函数来获取您想要的值:defaults.get(a,lambda: func(a))

完整的程序:

defaults.get(a,lambda: func(a))()

解决方案 3:浮华且有些混淆的布尔运算短路

作为第三种选择,您可以在 python 中使用 defaults = {None: (lambda: None),'': (lambda: None)} def func(arg): """Some function that cannot be called with None""" if arg is None: raise ValueError() print(f'func called with {arg}') def foo(a): return defaults.get(a,lambda: func(a))() def foo_b(a): defaults_b = {'bar': (lambda: 0),**defaults} return defaults_b.get(a,lambda: func(a))() if __name__ == '__main__': print(foo(None)) print(foo('')) print(foo(123)) print(foo(123)) print(foo_b(None)) print(foo_b('bar')) 的行为,根据您列出的所有默认值都是“falsy”(What is Truthy and Falsy? How is it different from True and False?)这一事实进行回复。在python中,and是短路的,这意味着如果a and ba或falsy,那么它已经知道False不能是a and b,所以它返回 True,或者如果 a 为真,则返回 a

因此,如果 ba,则 None 等于 defaults.get(a,True) and func(a)None and func(a) 是假的,所以 None 等于 None and func(a)。如果 None 不在 a 中,则 defaults 等于 defaults.get(a,True) and func(a),它等于 True and func(a),因此函数被调用。

请注意,如果您使用真实的默认值,例如,这将不起作用。 if func(a),对于可维护性来说可能很难理解 - 我只是想我会给出另一个选择。

defaults = {None: None,'': None,'bar': 'something'}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?