【问题标题】:Python conditional assignment operatorPython 条件赋值运算符
【发布时间】:2011-09-18 03:23:14
【问题描述】:

是否存在等效于 Ruby ||= 运算符(“如果未设置变量,请设置变量”)的 Python?

Ruby 中的示例:

 variable_not_set ||= 'bla bla'
 variable_not_set == 'bla bla'

 variable_set = 'pi pi'
 variable_set ||= 'bla bla'
 variable_set == 'pi pi'

【问题讨论】:

  • 如果未设置则不设置 - 如果当前值为 false(falsenil)则设置。当然,这种区别在语言中更为重要,例如将 0 和 "" 视为 false,但仍然
  • 这个 ruby​​ 运算符的用例是什么?
  • 这样做的方法是使用除 phihag 指示的 NameError 之外的尝试,但这在 Python 中没有任何意义,正如这里每个人所说的那样。在 Ruby 中,由于人们传递任意代码块以在函数内部运行的方式,它更有用。目标函数可能需要设置一个未在其执行的外部块中初始化的变量。 Python 中没有这种情况。

标签: python variables conditional


【解决方案1】:

我很惊讶没有人提供这个答案。它不像 Ruby 的 ||= 那样“内置”,但它基本上是等效的,并且仍然是单行的:

foo = foo if 'foo' in locals() else 'default'

当然,locals() 只是一个字典,所以你可以这样做:

foo = locals().get('foo', 'default')

【讨论】:

    【解决方案2】:

    我会用

    x = 'default' if not x else x
    

    比您在此处建议的所有替代方案短得多,而且直截了当。阅读,“如果未设置 x,则将 x 设置为‘默认’,否则将其保留为 x。”但是,如果您需要 None0False"" 为有效值,则需要更改此行为,例如:

    valid_vals = ("", 0, False) # We want None to be the only un-set value
    
    x = 'default' if not x and x not in valid_vals else x
    

    这种东西也只是乞求变成一个你可以在任何地方轻松使用的功能:

    setval_if = lambda val: 'default' if not val and val not in valid_vals else val
    

    此时,您可以将其用作:

    >>> x = None # To set it to something not valid
    >>> x = setval_if(x) # Using our special function is short and sweet now!
    >>> print x # Let's check to make sure our None valued variable actually got set
    'default'
    

    最后,如果你真的缺少你的 Ruby 中缀符号,你可以按照这个人的 hack 来重载 ||=|(或类似的东西):http://code.activestate.com/recipes/384122-infix-operators/

    【讨论】:

    • 你的第一个例子不起作用:>>> x = 'default' if not x else x Traceback (last recent call last): File "", line 1, in NameError: name 'x' is not defined
    • 这是一个错误的答案,如果 x 不存在就会失败。由于该问题要求一种测试存在性的方法,因此该解决方案将不起作用。
    • 这个答案解决了“条件赋值”的问题。如果没有设置变量,则设置它。当然,右边的一切都必须定义,否则会报错(我只是把它当作伪代码)。 x = "value1" if True else "value2"。一般来说。 x = 'value1' if condition else 'value2'
    【解决方案3】:

    不,替换是:

    try:
       v
    except NameError:
       v = 'bla bla'
    

    但是,想要使用这种结构是代码流过于复杂的标志。通常,您会执行以下操作:

    try:
       v = complicated()
    except ComplicatedError: # complicated failed
       v = 'fallback value'
    

    永远不要不确定是否设置了v。如果它是可以设置或不设置的众多选项之一,请使用字典及其允许默认值的 get 方法。

    【讨论】:

    • 不,你don't use except:
    • @delnan 我不想对complicated() 的性质做出具体假设。已添加。
    • 你确定? @emish 提供了一个更简单的解决方案。
    • 这是一个糟糕的解决方案。它不仅更复杂,而且在性能方面也更差。我会尽可能建议从问题中删除此解决方案。
    【解决方案4】:

    在 Python 2.5 及更高版本中有条件赋值 - 语法不是很明显,因此很容易错过。以下是你的做法:

    x = true_value if condition else false_value
    

    如需进一步参考,请查看Python 2.5 docs

    【讨论】:

    • 这不是我们要求的。
    【解决方案5】:

    不,不知道定义了哪些变量是一个错误,而不是 Python 中的一个特性。

    改用字典:

    d = {}
    d.setdefault('key', 1)
    d['key'] == 1
    
    d['key'] = 2
    d.setdefault('key', 1)
    d['key'] == 2
    

    【讨论】:

      【解决方案6】:

      (不能发表评论,否则我会这样做)我认为上面检查当地人的建议不太正确。应该是:

      foo = foo if 'foo' in locals() or 'foo' in globals() else 'default'
      

      在所有情况下都是正确的。

      然而,尽管它得到了支持,但我认为这也不能很好地模拟 Ruby 运算符。由于 Ruby 运算符允许的不仅仅是左侧的简单名称:

      foo[12] ||= something
      foo.bar ||= something
      

      异常方法可能最接近模拟。

      【讨论】:

        【解决方案7】:

        我通常这样做:

        def set_if_not_exists(obj,attr,value):
         if not hasattr(obj,attr): setattr(obj,attr,value)
        

        【讨论】:

          【解决方案8】:

          我认为你在找什么,如果你在字典里找东西,是setdefault方法:

          (Pdb) we=dict()
          (Pdb) we.setdefault('e',14)
          14
          (Pdb) we['e']
          14
          (Pdb) we['r']="p"
          (Pdb) we.setdefault('r','jeff')
          'p'
          (Pdb) we['r']
          'p'
          (Pdb) we[e]
          *** NameError: name 'e' is not defined
          (Pdb) we['e']
          14
          (Pdb) we['q2']
          

          *** KeyError: 'q2' (pdb)

          在我的示例中需要注意的重要一点是,当且仅当 setdefault 方法引用的键不存在时,setdefault 方法才会更改字典。

          【讨论】:

            【解决方案9】:

            我这样做...只是分享以防它对 OP 或其他任何人有用...

            def iff(value, default):
                return default if not value else value
            

            用法:

            z = iff(x,y) # z = x if and only if x is not null otherwise y
            

            【讨论】:

              【解决方案10】:

              我不确定我是否正确理解了这里的问题...尝试“读取”“未定义”变量名的值将触发NameError。 (见here, that Python has "names",不是变量...)。

              == 编辑 ==

              正如 delnan 在 cmets 中指出的那样,下面的代码并不健壮,并且会在很多情况下中断...

              尽管如此,如果您的变量“存在”,但具有某种虚拟值,例如 None,则以下方法可行:

              >>> my_possibly_None_value = None
              >>> myval = my_possibly_None_value or 5
              >>> myval
              5
              >>> my_possibly_None_value = 12
              >>> myval = my_possibly_None_value or 5
              >>> myval
              12
              >>> 
              

              (见this paragraph about Truth Values

              【讨论】:

              • 只要值可能是 0、“”、空字符串或其他任何“虚假”的值,就会中断。明确检查是否为is None
              • 哦,是的,你是对的,我没有想到这一点。感谢您的提示!我实际上从来没有需要做这个“或”的事情,我认为这是对这个问题的一个有效答案......但这个问题本身似乎与 Python 无关......
              猜你喜欢
              • 2018-06-09
              • 2011-03-06
              • 2015-06-06
              • 1970-01-01
              • 1970-01-01
              • 2011-03-11
              • 2010-11-21
              • 1970-01-01
              • 2017-07-16
              相关资源
              最近更新 更多