【问题标题】:Python: Dict get method always throws exception if the default is set to a function which throws exceptionPython:如果默认设置为抛出异常的函数,Dict get 方法总是抛出异常
【发布时间】:2016-07-19 07:45:34
【问题描述】:

在 get 方法中,如果我的默认函数有异常,那么无论字典中是否存在键,控件总是转到默认函数。这是演示相同的代码块。
编译器细节如下: Python 2.7.6(默认,2015 年 4 月 8 日,11:18:18) [GCC 4.7.2] 在 linux2 上

abc = 1
bcd = 2
class a(object):
    def test1(self):
        alphaNumMap = {
                    'a':abc,
                    'b':bcd
                    }
        num = alphaNumMap.get("a", self.add())
        print num


    def add(self):
        print "add called "
        raise Exception

if __name__ == "__main__":
    A = a()
    A.test1()

以上代码的输出如下:

add called 
Traceback (most recent call last):
File "test2.py", line 19, in <module>
A.test1()
File "test2.py", line 10, in test1
ipXpath = alphaNumMap.get("a",self.add())
File "test2.py", line 15, in add
raise Exception 
Exception

虽然预期的输出是 1 ,因为 'a' 存在于 dict alphaNumMap 中

【问题讨论】:

    标签: python exception dictionary data-structures default


    【解决方案1】:

    当然会引发异常。

    任何函数调用(在您的情况下为alphaNumMap.get("a",self.add()))必须首先评估其所有参数,在将控制权传递给函数之前。所以,add() 被调用,异常被引发,get() 根本没有被调用。

    最简单的方法是分配一个默认(异常)值,然后检查它:

    ipXpath = alphaNumMap.get("a", None) # instead of None there could be
    if ipXpath is None:                  # An_exceptional_value_specific_to_your_program
        ipXpath = self.add()
    

    表达可以更短(单行),但整个想法保持不变

    【讨论】:

    • 值得注意的是,add() 函数在准备get 的参数时由解释器调用,而get 在异常使事情脱轨之前甚至从未开始运行。您可以在回溯中看到这一点,它从test1 直接到add,而没有提及get 的框架。
    【解决方案2】:

    .get 将首先评估默认值,无论是否找到密钥。要解决这个问题,请执行以下操作:x=d.get(key) 然后if x is None: do stuff。

    .get 只是另一个恰好属于字典的函数。与 python 中的任何其他函数一样,所有参数都需要在函数执行之前进行评估。其中一个论点是self.add(),它在被评估时最终会引发异常。

    例如:

    >>> d = {1: 2}
    # Throws a NameError - fn is undefined
    >>> d.get(1, fn())
    # Prints 2 (here you need to be careful with the or - anything that evaluates to a False (in a boolean sense) will end up causing fn() to execute - maybe compare to a None, which is what get would have return for a missing key.
    >>> d.get(1) or fn() # Careful with the or here, alternative approach below
    >>> x = d.get(1)
    >>> y = x if x is not None else fn()
    

    【讨论】:

    • 这样做有什么原因吗?
    • 所以我们不能在 get 方法中默认调用函数。由于参数的评估是在获取方法评估之前。 @BAH
    • @user700110 是的,如果您不想在找到密钥后评估该函数,则不能将其放入 get
    猜你喜欢
    • 2011-08-17
    • 2012-02-18
    • 1970-01-01
    • 2012-08-23
    • 2017-07-11
    • 2013-05-24
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    相关资源
    最近更新 更多