2011-09-07 20 views
27

Python'da yeni bir RoR programcısıyım. Yalnızca önceden atanmamışsa, belirli bir değere bir değişken ayarlamamı sağlayacak sözdizimini bulmaya çalışıyorum. Temelde ben istiyorum:Python: Yok Varsa Değer Atama Var

# only if var1 has not been previously assigned

var1 = 4

+6

Var olmayan değişkenlere ne tür bir referans veriyorsunuz? Bildirilmiş ancak henüz başlatılmamış değişkenlere başvurmak ister misiniz? – mwcz

cevap

18

Bu programlama çok farklı bir tarzı olduğunu, ancak ben her zaman sadece içine

bar = None 
if foo(): 
    bar = "Baz" 

if bar is None: 
    bar = "Quux" 

benziyordu şeyler yeniden deneyin: is

if foo(): 
    bar = "Baz" 
else: 
    bar = "Quux" 

Ben önlemek için çalışıyorum, söylemek Bazı kod yollarının değişkenleri tanımladığı, ancak diğerlerinin olmadığı bir durumdur. Benim kodumda, hiçbir zaman tanımlanmış değişken kümesinin belirsizliğine neden olan bir yol yoktur (Aslında, genellikle bir adım daha ileri götürüyorum ve türünün kod yolundan bağımsız olarak aynı olduğundan emin olun). Bu sadece kişisel bir zevk meselesi olabilir, ama ben bu yazıyı, yazdığım zaman daha az açık olsa da, daha sonra okuduğumda daha kolay anlayabiliyorum. Bu olabilir

+37

Bu bir tek linerda bile kısaltılabilirdi 'bar = "Baz" foo() başka ise "Quux" – MatToufoutu

+0

@grokpot: Bu hiçbir şeyi değiştirmemeli, her iki kod parçacığı da aynı şeyler için alınmalı veya alınmamalıdır foo() ' – SingleNegationElimination

+0

@grokpot tarafından döndürülen: iki parçacığı dikkatle okuyun, eğer foo()' '' '' 'i döndürmediyse, test edilmez, 'bar' hala' None' ise test edilir. Eğer iki parçacığın farklı atamaları "bar" vermesine neden olacak foo() 'nin bir tanımını sağlayabiliyorsanız, size fantezi bir şişe viski (veya tercih ederseniz) alırım. – SingleNegationElimination

56

Bunu kontrol sonra yok olarak değişkenlerini başlatmak ve olmalıdır:

var1 = 4 if var1 is None else var1 
: olarak tek satırda yazılabilir

var1 = None 
if var1 is None: 
    var1 = 4 

veya kısayol kullanma (ancak Hiçbiri şey değişken adı vardır ve dolayısıyla NameError yükselteceği anlamına sonradan kullanarak etmediğini değişkenine atanan olmaz ve ayrıca bu

böyle bir şey yapmak bu bilgiyi kullanıp kullanamayacağınızı

var1 = var1 or 4 

alternatif) önerilir

try: 
    var1 
except NameError: 
    var1 = 4 

ama buna karşı tavsiye ederim.

+0

Bir değer atamak isterseniz, ya bir 'global' /' nonlocal' bildirimi ya da UnboundLocalError haricinde 'kullanın ve (değişkenin yerel olacağını ve global olarak ayarlanan değerin yok sayılacağını kabul edin) unutmayın. – delnan

+0

@delnan örneğimde UnboundLocalError'u nereden bulabilirim? –

+2

Daha sonra atama ('hariç'), 'var1' snippet modülü (yani, global) düzeyinde değilse veya bir 'global var1' satırı yoksa, yerel bir değişkendir. Henüz atanmamış bir yerel değişkene erişilmesi, 'NameError' yerine 'UnboundLocalError' (genel adlar için ayrılmıştır) yerine yükselir. – delnan

0

modül düzeyinde değişken o zaman "globals" kullanabilirsiniz kastediyorsan:

if "var1" not in globals(): 
    var1 = 4 

ancak ortak Python deyim None (bu kabul edilebilir bir değer olmadığını varsayarak) söylemek başlatmak için ve daha sonra if var1 is not None ile test.

+7

'da kontrol edebilirsiniz. Bu, yerel değişkenler üzerinde, 'locals()' globals üzerinde molaları kullanır ve ben nonwoals ile çalışır sanmıyorum. Bunu düzeltmek için, tüm kapsam belirleme kurallarına öykünmeli ya da her ikisinden biri varsayarak kodu yazmalıdır. – delnan

+2

@delnan: Yerel/nonglobal hakkında "Bu, modül seviyesinde bir değişkeni kastediyorsanız" ile kastediyorum. Bu aptalla ilgili "Bu yol çılgınlıktır" diyerek OP'ye söylemelisiniz, bana değil ... cevapta bu yolla söylenenler aslında bunun nasıl yapılması gerektiği değil. – 6502

15
var1 = var1 or 4 

tek sorun olduğunu var1 Yanlış veya 0 veya [], bunun yerine 4 seçecektir gibi Falsey değeri ise. Bu bir sorun olabilir.

+2

False'ı değerlendiren şeylerin tam listesi için [gerçek değer testi] 'ne bakın (https://docs.python.org/2/library/stdtypes.html#truth-value-testing), bazıları bazıları için şaşırtıcı olabilir. . – ecerulm

2

IfLoop'un yanıtı (ve MatToufoutu'nun yorumu) bağımsız değişkenler için harika çalışır, ancak listeler, tupllar veya sözlüklerdeki tekil girişler için benzer bir şey yapmaya çalışan herkes için bir yanıt vermek istedim.

Sözlükler

existing_dict = {"spam": 1, "eggs": 2} 
existing_dict["foo"] = existing_dict["foo"] if "foo" in existing_dict else 3 

İade {"spam": 1, "eggs": 2, "foo": 3}

Listeler

existing_list = ["spam","eggs"] 
existing_list = existing_list if len(existing_list)==3 else 
       existing_list + ["foo"] 

İade ["spam", "eggs", "foo"]

Tuples

existing_tuple = ("spam","eggs") 
existing_tuple = existing_tuple if len(existing_tuple)==3 else 
       existing_tuple + ("foo",) 

İade ("spam", "eggs", "foo")

(. "Tek" tuple tanımlamak için ("foo",) yılında virgül unutma)

listeleri ve küpe çözüm isterseniz daha karmaşık olacak Uzunluğunu kontrol etmekten ve sonuna kadar eklemekten daha fazlasını yapmak. Bununla birlikte, bu yapabileceğiniz şeylerin bir lezzetini verir.

+0

Bütün cevaplarınız bozuk. –

+1

@ SébastienDeprez Gerçekten doğruydu. İşaret ettiğin için teşekkürler. Bu yana sorunları ele almak için düzenlemeler yaptım. –

10

Ayrıca Ruby'den geliyorum, bu yüzden sözdizimini foo ||= 7 seviyorum.

Bulabildiğim en yakın şey budur.

foo = foo if 'foo' in vars() else 7 

gördüğüm insanlar dict için bunu:

try: 
    foo['bar'] 
except KeyError: 
    foo['bar'] = 7 

upadate: Ancak, son zamanlarda bu taş bulundu: Eğer böyle

foo['bar'] = foo.get('bar', 7) 

, Daha sonra düzenli bir değişken için şu gibi bir şey yapabilirsiniz:

vars()['foo'] = vars().get('foo', 7) 
+0

Bu, bir sınıftaki örnek değişkenler için nasıl çalışır? self.foo = ...? – CodeKid

+1

@CodeKid 'self.foo = self .__ dict __. Get ('foo', 7)' –

+1

@CodeKid Veya, 'self.foo = getattr (kendini, 'foo', 7)' – kkurian