2011-09-07 10 views
27

私はPythonを初めて使うRoRプログラマーです。以前に割り当てられていない変数のみを特定の値に設定できる構文を見つけようとしています。基本的に私がしたい:Python:Noneが存在する場合に値を割り当てます。

# only if var1 has not been previously assigned

var1 = 4

+6

存在しない可能性のある変数をどのような状況で参照していますか?宣言されているがまだ初期化されていない変数を参照しますか? – mwcz

答えて

18

これは、プログラミングの非常に異なるスタイルですが、私はいつもちょうどに

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

if bar is None: 
    bar = "Quux" 

のように見えたもの書き換えるしよう:言うことです

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

を、私は避けるために努力しますあるコードパスが変数を定義するが、他のコードパスは変数を定義しない状況。私のコードでは、定義された変数のセットのあいまいさを引き起こすパスはありません(実際には、私は通常これをさらに進め、コードパスに関係なくタイプが同じであることを確認します)。それはちょうど個人的な味の問題かもしれませんが、私はこのパターンを見ていますが、私がそれを書いているときにはあまり明白ではありませんが、後で読むときには分かりやすくなります。

+37

foo()else "Quux" ' – MatToufoutu

+0

@grokpot:これは何も変更すべきではなく、両方のコードスニペットを同じものにするべきかどうかは、' bar = "Baz" – SingleNegationElimination

+0

@grokpot:2つのスニペットを注意深く読んでください。 'foo()'が 'None'を返すかどうかはテストされていません。' bar'がまだ 'None'であるかどうかテストしています。 2つのスニペットに異なる割り当てを 'bar '与えるような' foo() 'の定義を与えることができるなら、私はあなたにスコッチの好きなものを買うでしょう(または好みのもの) – SingleNegationElimination

56

あなたはNoneに変数を初期化し、それを確認してください:

ように1行で記述することができ
var1 = None 
if var1 is None: 
    var1 = 4 

var1 = 4 if var1 is None else var1 

またはショートカットを使用してどれもあなたが何かは、変数名が存在し、したがってNameErrorを引き上げること、後に使用していないことを変数に割り当てられていないだろう、とあなたもこの

ような何かをするためにその知識を使用できるかどう

var1 = var1 or 4 

代わりに)推奨されていません

try: 
    var1 
except NameError: 
    var1 = 4 

しかし、私はそれに反対します。

+0

値を代入したい場合は、 'global' /' nonlocal'宣言が必要であるか、 'UnboundLocalError'を使わないでください(変数がローカルになり、グローバルに設定された値は無視されます)。 – delnan

+0

@delnanここで私の例ではUnboundLocalErrorを取得しますか? –

+2

スニペットがモジュール(すなわちグローバル)レベルにあるか、または 'global var1'という行がない限り、後で(exceptでは)割り当てのため、' var1'はローカル変数です。まだ割り当てられていないローカル変数にアクセスすると、 'NameError'(グローバル名に予約されている)の代わりに' UnboundLocalError'が呼び出されます。 – delnan

0

あなたはモジュールレベルで変数を意味するなら、あなたは「グローバル」を使用することができます

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

をしかし、一般的なPythonのイディオムは、(それが許容値ではありませんと仮定して)Noneを言って、それを初期化することで、 if var1 is not Noneでテストします。

+7

で「偽」と評価されているものを確認できます。これはグローバル変数で 'locals()'ブレークを使ってローカル変数を破壊し、どちらも非ローカル変数では動作しないと思います。これを修正するには、スコープ全体のルールをエミュレートするか、その両方を想定してコードを記述する必要があります。 – delnan

+2

@delnan:ローカル/非グローバルについてこれは私が「モジュールレベルの変数を意味する」という意味です。その馬鹿げたことについて「その方法は狂っている」あなたは私にではなくOPに言わなければなりません...答えの中で実際にはこれは何をするべきかではないと言われています。 – 6502

15
var1 = var1 or 4 

これは持っているかもしれない唯一の問題は、var1がfalsey値であれば、偽または0または[]のように、それは代わりに4を選ぶということです。それは問題かもしれません。

+2

Falseと評価されるものの完全なリストについては、[truth value testing](https://docs.python.org/2/library/stdtypes.html#truth-value-testing)を参照してください。いくつかは驚くかもしれません。 – ecerulm

2

IfLoopの答え(とMatToufoutuのコメント)は、スタンドアロン変数にはうまくいきますが、リスト、タプル、辞書の個々のエントリについて同様のことをしようとする人には答えを出したいと思っていました。

辞書

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

戻り{"spam": 1, "eggs": 2, "foo": 3}

リスト

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

戻り["spam", "eggs", "foo"]

タプル

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

戻り("spam", "eggs", "foo")

(「シングル」のタプルを定義するために("foo",)にカンマを忘れないでください。)

したい場合はリストやタプルソリューションはより複雑になります長さを確認して最後に追加するだけではありません。それにもかかわらず、これはあなたができることの味を与える。

+0

あなたの答えはすべて壊れています。 –

+1

@SébastienDeprezあなたは本当に正しかったです。指摘してくれてありがとう。私はそれ以来、問題を解決するために編集を行ってきました。 –

10

私もRubyから来ているので、構文は好きです。foo ||= 7

これは私が見つけることができる最も近いものです。

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

私が見てきた人々はdictのためにこれを行う:

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

Upadate: はしかし、私は最近、この宝石が見つかりました:あなたの場合は、そのような

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

を、通常の変数の場合は、次のようにします。

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

これはクラス内のインスタンス変数に対してどのように機能しますか? self.foo = ...? – CodeKid

+1

@CodeKid 'self.foo = self .__ dict __。get( 'foo'、7)' –

+1

@CodeKidまたは、 'self.foo = getattr(self、 'foo'、7)' – kkurian

関連する問題