同時に複数の変数を宣言するよりエレガントな方法


140

「同時に」複数の変数を宣言するには、次のようにします。

a, b = True, False

しかし、はるかに多くの変数を宣言する必要がある場合は、次第にエレガントさが低下します。

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True

これを行うためのより良い/エレガント/便利な方法はありますか?

これは非常に基本的なものでなければなりませんが、変数を格納するためにリストまたはタプルを使用した場合、次のように役立つようにするにはどうすればよいでしょうか。

aList = [a,b]

無効です、私はしなければなりません:

a, b = True, True

または何が欠けていますか?


リストを使用してこれらの値を保存しますか?辞書?(名前付き)タプル?
ジェフメルカド2011年

@クリス:私はそこに着いた。:)
ジェフメルカド

@JeffM:たぶん、しかし、どうすればよいかわかりません。リストに属するためには、それらを定義する必要があるようです(もちろん間違いかもしれません)
Trufa

3
@Trufa:値を格納するために多くの変数を宣言するつもりなら、それはすでに他のストレージの代替案を検討する必要がある兆候です。
ジェフメルカド2011年

1
@ user470379-名前はサンプルコードの名前であり、Trufaは実際のコードでそれらの名前を使用していないと思いました。
Chris Lutz、

回答:


52

他の人が示唆しているように、ブール値で10の異なるローカル変数を使用することがルーチンを書くための最良の方法である可能性は低いです(特に、実際に1文字の名前の場合:)。

何をしているのかによっては、代わりに辞書を使用することが理にかなっている場合があります。たとえば、1文字のフラグのセットにブールプリセット値を設定する場合は、次のようにします。

>>> flags = dict.fromkeys(["a", "b", "c"], True)
>>> flags.update(dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

必要に応じて、単一の代入ステートメントでそれを行うこともできます。

>>> flags = dict(dict.fromkeys(["a", "b", "c"], True),
...              **dict.fromkeys(["d", "e"], False))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

の2番目のパラメーターdictは、このために完全に設計されたものではありません。これは、のようなキーワード引数を使用して、ディクショナリーの個々の要素をオーバーライドできるようにするためのものd=Falseです。上記のコードは、呼び出された関数に渡されるキーワード引数の**セットに続く式の結果を爆破します。これは確かに辞書を作成するための信頼できる方法であり、人々は少なくともこのイディオムを受け入れているようですが、一部の人はそれをUnpythonicと考えるかもしれません。 </disclaimer>


このパターンを頻繁に使用する場合に最も直感的と思われるさらに別のアプローチは、フラグ名(単一文字の文字列)にマップされたフラグ値(TrueFalse)のリストとしてデータを定義することです。次に、このデータ定義を、フラグ名をフラグ値にマップする逆引き辞書に変換します。これは、ネストされたリスト内包表記を使用して非常に簡潔に行うことができますが、非常に読みやすい実装があります。

>>> def invert_dict(inverted_dict):
...     elements = inverted_dict.iteritems()
...     for flag_value, flag_names in elements:
...         for flag_name in flag_names:
...             yield flag_name, flag_value
... 
>>> flags = {True: ["a", "b", "c"], False: ["d", "e"]}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

関数invert_dictジェネレータ関数です。これは、生成、または収率が -それはつまり、繰り返しの値を返します。キーと値のペアを- 。これらのキーと値のペアは、初期flags辞書の2つの要素の内容の逆です。それらはdictコンストラクタに送られます。この場合、dictコンストラクタは引数としてディクショナリではなくイテレータを与えられているため、上記とは異なります。


@Chris Lutzのコメントを利用する:これを実際に単一文字の値に使用する場合は、実際に行うことができます

>>> flags = {True: 'abc', False: 'de'}
>>> flags = dict(invert_dict(flags))
>>> print flags
{'a': True, 'c': True, 'b': True, 'e': False, 'd': False}

これは、Python文字列が反復可能であるため、つまり値ごとに移動できるため機能します。文字列の場合、値は文字列内の個々の文字です。そうする際、彼らはforループで使用されている。この場合のように、イテラブルとして解釈されている['a', 'b', 'c']'abc'効果的に等価です。別の例は、のような反復可能関数をとる関数に渡される場合tupleです。

直感的に読み取れないので、私は個人的にはこれを行いません。文字列を見ると、リストとしてではなく単一の値として使用されることを期待しています。だから私は最初の行を見て、「さて、TrueフラグとFalseフラグがある」と思います。可能性はありますが、私はそれが進むべき道ではないと思います。利点としては、イテラブルとイテレータの概念をより明確に説明するのに役立つかもしれません。


invert_dict実際に辞書を返すように関数を定義することも悪い考えではありません。ルーチンがどのように機能するかを説明することは本当に役に立たないので、私はほとんどそれをしませんでした。


どうやらPython 2.7には辞書内包があるので、その関数を実装するための非常に簡潔な方法になります。Python 2.7がインストールされていないので、これは読者への練習問題として残しておきます:)

汎用性の高いitertoolsモジュールのいくつかの機能を組み合わせることもできます。彼らが言うように、それを行うには複数の方法があります。待って、Pythonの人々はそれを言わない。まあ、それはとにかくいくつかのケースで本当です。グイドは私たちに辞書の理解を与えたので、これを行うための一つの明白な方法があると思います。


1
['a', 'b', 'c']に短縮できることに注意してくださいlist('abc')。これは、次のようにdef truth_values(trues, falses): d = dict.from_keys(list(trues), True); d.update(dict.from_keys(list(falses), False)); return d使用されていますvalues = truth_values("abc", "de")
Chris Lutz

これは非常に包括的な答えのようです。ありがとうございます。私はそれをよく見て、あなたの散文、あなたの言っていることを実験します。それはおそらく本当ですが、それは自然とはならないので、私は少し読んで遊んでみてください。Pythonの弱点の1つである辞書以来、私はあなたが特に何を言っているのかを完全に理解するまで遊んでいます。どうもありがとう、私は戻ってきます:)
Trufa

5
@intuited私はあなたの答えにうんざりしています:あなたはOPの問題とは別の問題を定義し、あなたはこの他の問題に対して長い答えをすることを喜びます。彼はディクショナリ内の文字列と値を関連付けたくありません。識別子とそれぞれの値を持つオブジェクトを作成したいと考えています。
eyquem 2011年

5
@eyquem:長い答えは悪いですか?医者よ、自分を治して!
John Machin、2011年

5
これは質問に答えません、そしてそれはひいきです。以下の回答をご覧ください
kodu

225
a, b, c, d, e, g, h, i, j = (True,)*9
f = False

21
@Imray末尾のコンマ表記(d,)は、1項目のタプル(シーケンス型)を作成します。シーケンス型は、とりわけ、加算と乗算をサポートします。
duozmo 2014年

36
エレガントなトリックですが、リストなどの変更可能な要素でこれを使用することに注意してください。例えば、a, b, c = ([],)*33つのリストのインスタンスが、なりを作成していないabc同じインスタンスを指しています。
Zac、

5
私は自分のpythonコードをpythonicにするために無駄/時間を費やしている私の時間の多くを疑問に思う?
SARose

3
@Zacを正しく使用するには、を使用してくださいa, b, c = ([] for i in range(3))ソース。一貫性を保つために、この回答のバリエーション、つまりを使用することもできますa,b,c,d,e,g,h,i,j = (True for i in range(9)) f=(False i in range(1))
初心者C

これは、なぜ私がpythonが好きなのか、最近使っただけの例です。早く始めたいと思います。しかし、Web開発はプロジェクトによって異なります。
Angry 84

52

リスト/辞書を使用するか、独自のクラスを定義して、定義しているものをカプセル化しますが、これらすべての変数が必要な場合は、次のことができます。

a = b = c = d = e = g = h = i = j = True
f = False

1
変数はTrueとFalseのみに設定されません。
N 1.1

1
@ N1.1:それが何を意味するのか理解できませんでした。
Trufa '31 / 03 / 31、4:

@TrufaそれらがTrue / Falseのみに設定されている場合、提案された方法は完璧ですが、変数が異なるものに設定されている場合はどうなりますか?
N 1.1

@ N1.1:わかりました、ありがとうございます。この場合、それらはすべてブール値ですが、知っておくと便利です。おかげで
トルファ

5
これが危険なパターンである理由の説明については(実際の例ではありますが)、Notorious BIGを
duozmo

10

これは@ Jeff Mと私のコメントの詳細です。

これを行うと:

a, b = c, d

タプルのパックとアンパックで動作します。梱包ステップと開梱ステップを分けることができます。

_ = c, d
a, b = _

最初の行は_、最初の値がの要素cと2番目の要素の値の2つの要素を持つタプルを作成しますd。2行目は_タプルを変数aandにアンパックしますb。これにより、1つの大きな行が分解されます。

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True, True, True, True

2つの小さな行に:

_ = True, True, True, True, True, False, True, True, True, True
a, b, c, d, e, f, g, h, i, j = _

最初の行とまったく同じ結果が得られます(一方の部分に値または変数を追加したが、もう一方の部分を更新し忘れた場合も同じ例外が含まれます)。ただし、この特定のケースでは、ヤンの答えがおそらく最良です。

値のリストがある場合でも、それらを解凍できます。まず、それをタプルに変換する必要があります。例えば、以下はそれぞれに0と9の間の値を割り当てるaを介してj、それぞれ:

a, b, c, d, e, f, g, h, i, j = tuple(range(10))

編集:要素5(変数f)を除いてすべてをtrueに割り当てるためのきちんとしたトリック:

a, b, c, d, e, f, g, h, i, j = tuple(x != 5 for x in range(10))

最後の1つが可能かどうかは知りませんでした。ぜひ試してみます。確かに巧妙なトリックであり、重宝するかもしれません。
Trufa

5

人々が「リストまたはタプルまたはその他のデータ構造を使用する」ことを提案しているとき、彼らが言っているのは、気になる多くの異なる値がある場合、ローカル変数としてすべてに別々に名前を付けることは最善の方法ではないかもしれないということです物事を行う。

代わりに、それらを1つのローカル変数に格納できるより大きなデータ構造にまとめることができます。

intuitedはこのためのディクショナリの使用方法を示し、Chris Lutzは個別の変数にアンパックする前に一時ストレージにタプルを使用する方法を示しましたが、考慮すべきもう1つのオプションはcollections.namedtuple、値をより永続的にバンドルすることです。

だからあなたは次のようなことをするかもしれません:

# Define the attributes of our named tuple
from collections import namedtuple
DataHolder = namedtuple("DataHolder", "a b c d e f g")

# Store our data
data = DataHolder(True, True, True, True, True, False, True)

# Retrieve our data
print(data)
print(data.a, data.f)

もちろん、実際のコードでは、「DataHolder」やアルファベットの文字よりも意味のある名前を使用することが望ましいでしょう。


あなたの答えをありがとう、私はこれをオプションとしてチェックアウトします、問題は(この特定のケースでは)不変の構造を持つことは役に立たないかもしれないということです。これがどうなったのかについては後でコメントしますが、再び感謝します!
Trufa 2011年

通常のクラスでも同じことができます-の定義はDataHolderもう少し冗長になります。
ncoghlan 2011年

4

実際、何が問題なのですか?

10 abcdefghijが本当に必要であるか、または必要な場合、aを書き込んでbを書き込み、cを書き込むという他の可能性はありません。 ....

値がすべて異なる場合は、例のように書く必要があります

a = 12
b= 'sun'
c = A() #(where A is a class)
d = range(1,102,5)
e = (line in filehandler if line.rstrip())
f = 0,12358
g = True
h = random.choice
i = re.compile('^(!=  ab).+?<span>')
j = [78,89,90,0]

つまり、「変数」を個別に定義します。

または、別の記述を使用して、使用する必要はありません_

a,b,c,d,e,f,g,h,i,j =\
12,'sun',A(),range(1,102,5),\
(line for line in filehandler if line.rstrip()),\
0.12358,True,random.choice,\
re.compile('^(!=  ab).+?<span>'),[78,89,90,0]

または

a,b,c,d,e,f,g,h,i,j =\
(12,'sun',A(),range(1,102,5),
 (line for line in filehandler if line.rstrip()),
 0.12358,True,random.choice,
 re.compile('^(!=  ab).+?<span>'),[78,89,90,0])

それらのいくつかが同じ値でなければならない場合、それは書くには長すぎるという問題です

a, b, c, d, e, f, g, h, i, j = True, True, True, True, True, False, True ,True , True, True 

それからあなたは書くことができます:

a=b=c=d=e=g=h=i=k=j=True
f = False

何が問題なのかよくわかりません。コードを記述したい場合は、指示と定義の記述に必要な文字を使用する必要があります。ほかに何か ?

あなたの質問はあなたが何かを誤解している兆候ではないのでしょうか。

「」を書き込んでもa = 10、「値が変更されるメモリのチャンク」という意味で変数作成することはありません。この指示:

  • タイプintegerと値が10のオブジェクトの作成と、現在のネームスペース内のこのオブジェクトへの名前「a」のバインディングをトリガー

  • または、ネームスペースの名前「a」をオブジェクト10に再度割り当てます(「a」は以前に別のオブジェクトにバインドされていたため)。

私は、FalseまたはTrueを指す10個の識別子a、b、cを定義するユーティリティが表示されないので、それを言います。これらの値が実行中に変化しない場合、なぜ10個の識別子があるのですか?そして、それらが変更された場合、なぜ最初に識別子を定義するのですか?事前に定義されていない場合は、必要なときに作成されます

あなたの質問は私には奇妙に見えます


2

あなたが私に間違った方法であなたの問題に近づいているように聞こえます。

タプルを使用するようにコードを書き直すか、すべてのデータを格納するクラスを記述します。


コードをちらりと見なくても、ありがとうございました:)これは理想的ではないことを理解しています。私はあなたの要点を理解しています。
トルファ、2011年

1
そうですね、そうですね。それはそれがどのように聞こえるかです。リファクタリングはおそらく問題を解決します。あなたの問題はスタイルの問題であり、機能的な問題ではないため、かなりのmetadvice以外のものを提供することは困難です。
richo

1

投票数の多い回答が好きです。ただし、次のようにリストには問題があります。

  >> a, b = ([0]*5,)*2
  >> print b
  [0, 0, 0, 0, 0]
  >> a[0] = 1
  >> print b
  [1, 0, 0, 0, 0]

これは非常に詳細に議論されています(ここ)が、要点はそれab同じオブジェクトであり、a is b戻るTrue(と同じid(a) == id(b))です。したがって、インデックスを変更するab、との両方がリンクされているため、両方のインデックスが変更されます。これを解決するには、次のようにします(ソース)

>> a, b = ([0]*5 for i in range(2))
>> print b
[0, 0, 0, 0, 0]
>> a[0] = 1
>> print b
[0, 0, 0, 0, 0]

これは、「望ましい」直感的な結果を持つトップアンサーのバリアントとして使用できます。

>> a, b, c, d, e, g, h, i = (True for i in range(9))
>> f = (False for i in range(1)) #to be pedantic

1

あなたの場合、私はYAMLを使用します。

これは、複数のパラメータを処理するための洗練されたプロフェッショナルな標準です。値は別のファイルから読み込まれます。このリンクでいくつかの情報を見ることができます:

https://keleshev.com/yaml-quick-introduction

ただし、Googleの方が簡単です。標準であるため、何百もの情報があり、理解に最も適したものを見つけることができます。;)

宜しくお願いします。


こんにちはHenrique、SOへようこそ、あなたの答えをありがとう!次の質問に回答する前に必ず回答を読んでください。
ディギー。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.