Python'un Ruby'de || = gibi bir "or equals" işlevi var mı?


83

Değilse, bunu yapmanın en iyi yolu nedir?

Şu anda yapıyorum (bir django projesi için):

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

ama oldukça garip. Ruby'de şöyle olur:

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

bu çok daha güzel.


23
Bu iki kod bitinin aslında çok farklı olduğuna dikkat edin: Python sürümü, diktede değilse 5'e ayarlar; burada Ruby sürümü de herhangi bir yanlış değere ayarlanmışsa 5'e ayarlar.
Glenn Maynard

2
@Glenn, çok farklı değil , ama oldukça farklı. Başlatılmamış bir hash değeri döndüğünden nil(boole bağlamında yanlış) bu deyim genellikle tam olarak sean'ın kullandığı amaç için kullanılır. Deyim, ancak elbette nilve false
hash'deki

8
@banister: "Çok" ile "oldukça" arasındaki çizgiyi nereye çekeceğimi bilmiyorum, ama mesele şu ki bunlar eşdeğer ifadeler değil ve farkı anlamak önemli. (False, genellikle bir hash içinde geçerli bir değerdir ve bir boole alanı için varsayılanı true olarak ayarlamak istediğinizde sizi ısırır; bu, Ruby'nin deyiminin önemli bir eksikliğidir.)
Glenn Maynard

Evet, Python örneği tanımlı veya perl'de//= bulduğunuz gibi . Sanırım aynı zamanda Perl'den geliyor. ||=
draegtun

Ah iyi noktalar, hepsi. Bu farkı fark etmemiştim.
Sean W.

Yanıtlar:


188

Kabul edilen cevap diktler için iyidir, ancak başlık Ruby'nin || = operatörüne genel bir eşdeğer arar. Python'da || = gibi bir şey yapmanın yaygın bir yolu

x = x or new_value

36
Bu cevap büyük olasılıkla bir Google aramasından buraya gelenlerin aradığı şeydir.
gradi3nt

Bu gerçekten en iyi cevap.
AdamC

6
Ruby'den farklı olarak, bu kodun yalnızca xönceden tanımlanmışsa çalışacağını unutmayın (örneğin None, bir sınıf başlatma yönteminde olarak ayarlanmışsa ).
oli

3
Doğru, bu tam olarak Ruby'nin || = gibi davranmaz. Dikkat edilmesi gereken başka bir şey de x'in 'doğruluğu'. Python'da x == 0 ise, 0 yanlış kabul edildiğinden new_value alırsınız, ancak Ruby'de 0 alırsınız.
Joseph Sheedy

1
Bu || = kadar verimli mi? || = boş olmadığı sürece bir atama yapmaz, ancak bu her zaman bir atama yapar. Python derleyicisi düşündüğümden daha akıllı mı?
jsarma

17

dictvardır setdefault().

Yani eğer request.sessionbir dict:

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

Belirsiz şekilde benzer, ancak hiçbir şekilde Ruby'nin || = eşdeğeri değildir.
AdamC

1
Anahtar zaten ayarlanmış olsa bile varsayılan ifadenin değerlendirilmesinden önemli ölçüde farklıdır. Varsayılan değeri değerlendirmeden veya anahtara birden fazla erişmeden veya her ikisine birden erişmeden orijinal soruyu çözmenin bir yolu yoktur.
slinkp

13

Hassas cevap: Hayır. Python tek yok yerleşik operatör opçevirebilir x = x or yiçine x op y.

Ama neredeyse öyle. Bitsel veya eşittir operatörü ( |=) , her iki işlenen de bir uyarı ile boole olarak değerlendiriliyorsa yukarıda açıklandığı gibi işlev görür. (Uyarı nedir? Cevap elbette aşağıdadır.)

İlk olarak, işlevselliğin temel gösterimi:

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

Uyarı, python'un kesin olarak yazılmamasından kaynaklanmaktadır ve bu nedenle, değerler bir ifadede boole olarak değerlendirilse bile, bitsel bir operatöre verilirse kısa devre yapılmayacaktır. Örneğin, bir listeyi temizleyen ve Truesilinen öğeler varsa geri dönen bir mantıksal işlevimiz olduğunu varsayalım :

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

Şimdi kısa devre davranışını şu şekilde görebiliriz:

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

Output: True [1, 2, 3]

Bununla birlikte, orbit düzeyinde veya ( |) ' ye geçmek kısa devreyi kaldırır, böylece işlev my_clear_listyürütülür.

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

Output: True []

Yukarıdaki x = x | my_clear_list(lst)eşdeğerdir x |= my_clear_list(lst).


10

Varsayılanı ayarlamak, bunu bir ara yazılımda veya başka bir şeyde yapıyorsanız mantıklıdır, ancak bir istek bağlamında varsayılan bir değere ihtiyacınız varsa:

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

bonus: işte ||=Python'da gerçekten nasıl yapılacağı .

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

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

1

Genel olarak kullanabilirsiniz dict[key] = dict.get(key, 0) + val.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.