Python在Ruby中是否具有像|| =这样的“或等于”函数?


82

如果没有,什么是最好的方法?

现在我正在做(对于Django项目):

if not 'thing_for_purpose' in request.session:
    request.session['thing_for_purpose'] = 5

但它很尴尬。在Ruby中,它将是:

request.session['thing_for_purpose'] ||= 5

更好。


23
请注意,这两位代码实际上是非常不同的:如果根本不在字典中,则Python版本会将其设置为5;如果将Ruby版本设置为任何假值,则将其设置为5。
格伦·梅纳德

2
@Glenn,不是不同,但完全不同。由于未初始化的哈希值返回nil(在布尔上下文中为false),因此该习语通常完全用于肖恩使用它的目的。成语只能尽管如果,当然,nilfalse在散列不合法的值(这是非常往往是真的,那么这个成语是罚款)
horseyguy

8
@banister:我不知道在“非常”和“非常”之间的界限是什么,但是重点是这些不是等同的陈述,理解差异很重要。(False通常是散列中的有效值,当您想将布尔字段的默认值设置为true时,它会咬住您;这是Ruby惯用语的重大缺陷。)
Glenn Maynard 2010年

是的,Python示例更类似于define -or,就像//=您在perl中找到的一样。我认为这||=也源于Perl。
draegtun 2010年

很好,全部。我没有注意到这种差异。
肖恩·W.2010年

Answers:


186

可接受的答案对字典很有用,但是标题寻求的通用含义与Ruby的|| =运算符相同。在Python中执行|| =之类的常见方法是

x = x or new_value

36
这个答案可能是来自Google搜索的人们所寻找的。
gradi3nt

这确实是最好的答案。
AdamC

6
请注意,与Ruby不同,此代码仅x在预先定义的情况下才有效(例如,None在类初始化方法中设置为)。
奥利

3
没错,这与Ruby的|| =并不完全一样。需要注意的另一件事是x的“真实性”。如果x == 0在Python中,你会得到NEW_VALUE因为0被认为是假的,但在Ruby中,你会得到0
约瑟夫·希迪

1
这和|| =一样有效吗?|| =除非为null,否则不会执行分配,但这始终会执行分配。python编译器比我想象的还要聪明吗?
jsarma '16

17

dictsetdefault()

所以如果request.sessiondict

request.session.setdefault('thing_for_purpose', 5)

大致相似,但绝不等同于Ruby的|| =。
AdamC

1
它的显着不同之处在于,即使已设置键,也会对默认表达式进行求值。没有评估默认值或多次访问密钥,或两者都不是,无法解决原始问题。
slinkp

10

如果要在中间件或其他某种方式中进行设置,则设置默认值是有意义的,但是如果在一个请求的上下文中需要默认值,则可以执行以下操作:

request.session.get('thing_for_purpose', 5) # gets a default

红利:这是||=在Python中真正做的方法。

def test_function(self, d=None):
    'a simple test function'
    d = d or {}

    # ... do things with d and return ...

10

精确答案:否 。Python没有op可以转换x = x or y为的单个内置运算符x op y

但是,几乎可以做到。如果两个操作数都被视为布尔值,请注意, 按位或等于运算符(|=如上所述运行。(警告是什么?答案当然在下面。)

首先,功能的基本演示:

x = True
x    
Out[141]: True

x |= True
x    
Out[142]: True

x |= False
x    
Out[143]: True

x &= False
x    
Out[144]: False

x &= True
x    
Out[145]: False

x |= False
x    
Out[146]: False

x |= True
x   
Out[147]: True

需要注意的是,由于python没有严格类型化,因此即使将值视为表达式中的布尔值,如果将它们提供给按位运算符,它们也不会短路。例如,假设我们有一个布尔函数,该函数清除列表并True在删除了元素后返回:

def  my_clear_list(lst):
    if not lst:
        return False
    else:
        del lst[:]
        return True

现在,我们可以看到短路行为:

x = True
lst = [1, 2, 3]
x = x or my_clear_list(lst)
print(x, lst)

Output: True [1, 2, 3]

但是,将其切换or为按位或(|)可消除短路,因此该功能得以my_clear_list执行。

x = True
lst = [1, 2, 3]
x = x | my_clear_list(lst)
print(x, lst)

Output: True []

以上,x = x | my_clear_list(lst)等同于x |= my_clear_list(lst)


1

通常,您可以使用dict[key] = dict.get(key, 0) + val

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.