Python 有类似于 Ruby 中的 | | = 的“或等于”函数吗?

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

现在我正在做(为一个 django 项目) :

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

但是很尴尬,在 Ruby 里是这样的:

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

这样好多了。

47368 次浏览

dict has setdefault().

So if request.session is a dict:

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

Setting a default makes sense if you're doing it in a middleware or something, but if you need a default value in the context of one request:

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

bonus: here's how to really do an ||= in Python.

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


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

Jon-Eric's answer's is good for dicts, but the title seeks a general equivalent to 's ||= operator.

A common way to do something like ||= in Python is

x = x or new_value

In general, you can use dict[key] = dict.get(key, 0) + val.

Precise answer: No. Python does not have a single built-in operator op that can translate x = x or y into x op y.

But, it almost does. The bitwise or-equals operator (|=) will function as described above if both operands are being treated as booleans, with a caveat. (What's the caveat? Answer is below of course.)

First, the basic demonstration of functionality:

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

The caveat is due python not being strictly-typed, and thus even if the values are being treated as booleans in an expression they will not be short-circuited if given to a bitwise operator. For example, suppose we had a boolean function which clears a list and returns True iff there were elements deleted:

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

Now we can see the short-circuited behavior as so:

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


Output: True [1, 2, 3]

However, switching the or to a bitwise or (|) removes the short-circuit, so the function my_clear_list executes.

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


Output: True []

Above, x = x | my_clear_list(lst) is equivalent to x |= my_clear_list(lst).