2009-11-26 7 views
5

私はいくつかの変数を持っています。最初のものをTrueに評価するか、それ以外の場合はデフォルト値を返します。真に評価する最初の変数を選択するPythonic方法

たとえば、私はa,bおよびcを持っています。私の既存のコード:

result = a if a else (b if b else (c if c else default)) 

私が考えていたもう一つのアプローチ:

result = ([v for v in (a, b, c) if v] + [default])[0] 

しかし、彼らの両方が乱雑に感じるので、より多くのPython的な方法はありますか?

+0

私は "pythonic"について知らないけど、最初のものは好きです。素敵でリスピーで読みやすい。 – mtvee

+6

「定義済み」はどういう意味ですか?たとえばbが未定義の場合、NameErrorが返されます。あなたのコードは、変数が定義されているが空/ゼロ/偽であるかどうかをチェックします。 –

+3

Pythonでは変数を定義しないので、オブジェクトに名前をバインドすることに注意してください。 –

答えて

20

bool(value)==Trueの最初の値を返すことを意味しましたか?次に、あなただけのboolean operators return last evaluated argumentという事実に頼ることができます:1つの変数が「定義されて」いません

result = a or b or c or default 
+1

NB(OPに)空文字列(' "" ')にはfalseがありますブール値( 'bool(" ")== False');あなたがあなたのプログラムでそれを "偽"とみなさないなら、それを念頭に置いてください。 '()'(空のタプル)、 '{}'(空のdict)、 '[]'(空のリスト)、ゼロ(任意の数値型)にも同じです。 – tzot

17

場合は、その名前にアクセスすることはできません。したがって、 'a'への参照はNameError例外を発生させます。一方で

、あなたのような何かを持っている場合:これはすべてのケースで動作するかどうか

a = None 
b = None 
c = 3 

をあなたは

default = 1 
r = a or b or c or default 
# r value is 3 
+0

質問者が提示した2つのオプションのどちらも、同じNameErrorExceptionを実行しませんでしたか? – donut

+1

そうです。何かを割り当てる前に変数を読むことはできません。 –

1

を行うことができますが分からないのですが、これはこの場合のために動作します。

a = False 
b = "b" 
c = False 
default = "default" 
print a or b or c or default # b 
1

これはいかがですか?

a=None 
b=None 
c=None 
val= reduce(lambda x,y:x or y,(a,b,c,"default")) 
print val 

上記のプリント"default"。いずれかの入力が定義されている場合、valは最初に定義された入力を含みます。

5

限りdefaultがTrueに評価される:あなたは他の回答とは対照的に、このような何かを(行うことができ

result = next((x for x in (a, b, c, d , e, default) if x)) 
+4

'next'を使うことを決めた場合は、' default'引数を使うこともできます – abyx

2

これはあなたが「の行方不明」を定義するを持っていないソリューションですNone又はFalse)のいずれかであるとして値:NameErrorsを回避するために

b = 6 
c = 8 

def first_defined(items): 
    for x in items: 
     try: 
      return globals()[x] 
      break 
     except KeyError: 
      continue 

print first_defined(["a", "b", "c"]) 

、B又はCが定義されていない:関数を文字列のリストを与える代わりに変数参照(存在しない参照を渡すことはできません)。 'globals()'スコープ外の変数を使用している場合は、デフォルトの引数でgetattrを使用できます。

-

、a、b及びcが定義されている場合、私は(空の文字列、なしまたはFalseはブールFalseに評価されなかったという事実を考慮して)このような何かのために行くだろう:

a = None 
b = 6 
c = 8 

def firstitem(items): 
    for x in items: 
     if x: 
      return x 
      break 
     else: 
      continue 

print firstitem([a, b, c]) 
+1

リターン後に 'break'する必要はありません。すでにループから外れています。ループの終わりに 'else:continue'する必要もありません。それは何とか起こります。 –

1

definedを意味する場合、ever assigned any value whatsoever to in any scope accessible from hereを意味する場合、「未定義」変数にアクセスしようとすると、NameError例外(またはそのサブクラスが発生しますが、NameErrorをキャッチするとサブクラスもキャッチされます)が発生します。だから、実行するための最も簡単な方法は、文字通り、あなたが尋ねる絶対に変なタスクは、次のとおりです。

for varname in ('a', 'b', 'c'): 
    try: return eval(varname) 
    except NameError: pass 
return default 

どれ疑惑の解決策は、「定義された」については、上記の意味の下では動作しません除いて/試しを欠いています。特定のスコープを探索することに基づくアプローチは、他のスコープを欠場するか、またはevalがそう簡単に行うスコープオーダーロジックを複製しようとするとかなり複雑になります。

"定義されている"とは、実際には "trueと評価される値を割り当てられます(falseとは対照的に")、つまりすべての値がと定義されています(ただし、真の値ではなく)、既に提案されているa or b or c or defaultが最も簡単なアプローチになります。しかし、それは "定義された"という言葉とはまったく異なった意味です。 - )

関連する問題