동시에 여러 변수를 선언하는보다 우아한 방법


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

아니면 내가 무엇을 놓치고 있습니까?


목록을 사용하여 해당 값을 저장 하시겠습니까? 사전? 명명 된 튜플?
Jeff Mercado

@Chris : 나는 거기에 도착했다. :)
Jeff Mercado

@JeffM : 어쩌면 어떻게해야할지 모르겠다. 목록에 속하기 위해 그것들을 정의해야한다고 생각한다 (물론 틀릴 ​​수도있다)
Trufa

3
@Trufa : 값을 저장하기 위해 많은 변수를 선언하려는 경우 이미 다른 저장 장치 대안 IMHO를 고려해야합니다.
Jeff Mercado

1
@ user470379-이름은 예제 코드에 불과하며 Trufa는 실제 코드에서 해당 이름을 사용하지 않는다고 가정합니다.
Chris Lutz

답변:


52

다른 사람들이 제안했듯이 부울 값과 함께 10 가지 지역 변수를 사용하는 것이 루틴을 작성하는 가장 좋은 방법은 아닙니다 (특히 실제로 하나의 문자 이름이있는 경우).

수행중인 작업에 따라 사전을 대신 사용하는 것이 좋습니다. 예를 들어 한 글자 플래그 집합에 대해 부울 사전 설정 값을 설정하려면 다음을 수행하십시오.

>>> 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}

두 번째 매개 변수 dict는이를 위해 완전히 설계된 것은 아닙니다. 실제로 키워드 인수를 사용하여 사전의 개별 요소를 재정의 할 수 있습니다 d=False. 위의 코드는 표현식 결과를 호출 된 함수에 전달되는 키워드 인수** 세트로 분류 합니다. 이것은 확실히 사전을 만드는 신뢰할 수있는 방법이며 사람들은 적어도이 관용구를 받아들이는 것처럼 보이지만 일부는 Unpythonic으로 간주 할 수 있습니다. </disclaimer>


이 패턴을 자주 사용하는 경우 가장 직관적 인 또 다른 방법은 데이터 를 플래그 이름 (한 문자 문자열)에 매핑 된 플래그 값 ( True, False) 목록으로 정의하는 것 입니다. 그런 다음이 데이터 정의를 플래그 이름을 플래그 값에 맵핑하는 반전 된 사전으로 변환하십시오. 중첩 된 목록 이해로 간결하게 수행 할 수 있지만 다음은 매우 읽기 쉬운 구현입니다.

>>> 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사전 의 두 요소 내용의 역수입니다 . 그들은 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}

이것은 파이썬 문자열이 반복 가능 하기 때문에 작동합니다 . 즉, 값별로 값을 이동할 수 있습니다. 문자열의 경우 값은 문자열의 개별 문자입니다. 그들은 그들이 for 루프에서 사용되는이 경우로, 반복 가능 객체로 해석되고 그래서 ['a', 'b', 'c']하고 'abc'효과적으로 동일합니다. 또 다른 예는 iterable을 취하는 함수에 전달 될 때와 같습니다 tuple.

나는 개인적으로 이것을 직관적으로 읽지 않기 때문에 이것을하지 않을 것입니다 : 문자열을 볼 때 문자열이 목록이 아닌 단일 값으로 사용될 것으로 기대합니다. 첫 번째 줄을보고 "알겠습니다. True 플래그와 False 플래그가 있습니다."라고 생각합니다. 따라서 가능성이 있지만 그것이 갈 길이라고 생각하지 않습니다. 거꾸로, iterables와 iterators의 개념을보다 명확하게 설명하는 데 도움이 될 수 있습니다.


invert_dict실제로 사전을 반환 하도록 함수를 정의 하는 것도 나쁜 생각이 아닙니다. 루틴의 작동 방식을 설명하는 데 실제로 도움이되지 않기 때문에 대부분 그렇게하지 않았습니다.


분명히 파이썬 2.7에는 사전 이해력이있어 그 기능을 구현하는 매우 간결한 방법이 될 것입니다. 파이썬 2.7이 설치되어 있지 않기 때문에 독자에게 연습으로 남겨 둡니다. :)

다양한 itertools 모듈 의 일부 기능을 결합 할 수도 있습니다 . 그들이 말하는 것처럼, 한 가지 이상의 방법이 있습니다. 잠깐, 파이썬 사람들은 그렇게 말하지 않습니다. 어쨌든 그것은 사실입니다. 귀도는 우리에게 사전 이해력을 주어서 이것을 할 수있는 분명한 방법 이있을 것이라고 생각합니다.


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")
크리스 루츠

대단히 감사합니다. 이것은 매우 포괄적 인 답변처럼 보입니다. 나는 당신이 무엇을 말하고 있는지, 당신이 말하는 것을 잘 살펴보고 실험 할 것입니다. 아마도 사실이지만, 자연스럽지 않을 수도 있으므로 파이썬에서 내 약점 중 하나 인 사전이 있기 때문에 특별히 의미하는 바를 완전히 얻을 때까지 조금 읽고 놀아보십시오. 대단히 감사합니다,
돌아올께

5
@intuited 나는 당신의 대답에 열중합니다 : 당신은 OP의 문제 이외의 다른 문제를 정의 하고이 다른 문제에 대한 긴 대답을 기쁘게 생각합니다. 사전에 문자열과 값을 연결하고 싶지 않고 식별자와 각 값에 대한 개체를 생성하려고합니다.
eyquem

5
@ eyquem : 긴 답변이 나쁩니 까? 의사, 당신을 치유하십시오!
John Machin

5
이것은 질문에 대한 답이 아니며 후원입니다. 아래 답변을 참조하십시오
kodu

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

21
@Imray Trailing 쉼표 표기법 (d,)은 시퀀스 유형 인 하나의 항목 튜플을 만듭니다. 시퀀스 타입 은 다른 연산들 중에서 더하기와 곱셈을 지원합니다.
duozmo

36
우아한 트릭이지만 목록과 같은 가변 요소에 이것을 사용하는 것을 알고 있어야합니다. 예를 들어 a, b, c = ([],)*33 개 목록 인스턴스하지만 차종 만들지 않습니다 a, b그리고 c같은 인스턴스를 가리키는.
Zac

5
파이썬 코드를 파이썬으로 만들려고 낭비하는 데 많은 시간을 보내고 있습니까?
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

이것은 왜 파이썬을 좋아하는지에 대한 예입니다. 최근에만 사용하십시오. 더 일찍 시작하길 바랍니다. 그러나 웹 개발은 프로젝트에 따라 다릅니다.
Angry 84

52

목록 / 사전을 사용하거나 자신의 클래스를 정의하여 정의하고있는 것을 캡슐화하십시오. 그러나 이러한 변수가 모두 필요한 경우 다음을 수행 할 수 있습니다.

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

1
vars는 True & False로만 설정되지 않습니다.
N 1.1

1
@ N1.1 : 나는 당신이 그 의미를 이해할 수 없었습니다.
Trufa

@Trufa True / False로만 설정된 경우 제안 된 방법은 완벽하지만 변수가 다른 것으로 설정되면 어떻게됩니까?
N 1.1

@ N1.1 : 오, 나는 당신이 의미하는 것을 얻습니다. 설명을 주셔서 감사합니다! 이 경우, 그들은 모두 바보이지만 아는 것이 좋습니다. 감사합니다
Trufa

5
이것이 왜 위험한 패턴인지에 대한 설명은 (작동 예제 임에도 불구하고) Notorious BIG
duozmo

10

이것은 @ Jeff M 에 대한 설명 과 내 의견입니다.

이렇게하면 :

a, b = c, d

튜플 포장 및 포장 풀기와 함께 작동합니다. 포장 및 포장 풀기 단계를 분리 할 수 ​​있습니다.

_ = c, d
a, b = _

첫 번째 줄 _은 두 요소를 갖는 튜플을 생성합니다 . 첫 번째 값은 값이 c있고 두 번째 요소 는 값이입니다 d. 두 번째 행은 언팩 _변수로 튜플 ab. 이것은 하나의 거대한 라인을 분해합니다.

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

두 개의 작은 라인으로 :

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

첫 번째 줄과 동일한 결과를 제공합니다 (한 부분에 값이나 변수를 추가하지만 다른 부분을 업데이트하지 않은 경우 동일한 예외 포함). 그러나이 특정 경우 yan의 대답 이 가장 좋습니다.

값 목록이 있으면 여전히 압축을 풀 수 있습니다. 먼저 튜플로 변환해야합니다. 예를 들어, 다음은 각각 0에서 9 사이의 값을 각각의 athrough에 할당합니다 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))

나는 마지막 것이 가능하다는 것을 몰랐다. 나는 확실히 시도해 볼 것이다. 실제로 깔끔한 트릭이며 유용 할 수있다!
Trufa

5

사람들이 "목록 또는 튜플 또는 다른 데이터 구조 사용"을 제안 할 때, 그들이 말하는 것은, 당신이 관심있는 다른 많은 값을 가질 때, 지역 변수로서 모두 따로 명명하는 것이 최선의 방법이 아닐 수 있다는 것입니다 일을합니다.

대신, 단일 로컬 변수에 저장 될 수있는 더 큰 데이터 구조로 함께 모을 수 있습니다.

intuited는 사전을 사용하는 방법을 보여 주었고 Chris Lutz는 별도의 변수로 압축을 풀기 전에 임시 저장을 위해 튜플을 사용하는 방법을 보여 주었지만 고려해야 할 또 다른 옵션 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

평범한 클래스에서도 똑같은 일을 할 수 있습니다. 정의 DataHolder는 조금 더 장황합니다.
ncoghlan

4

실제로 무엇이 문제입니까?

당신이 정말로 필요하거나 원하는 경우 10 , b를 , C는 , d를 , 전자는 , f를 , g는 , 시간은 , 내가 , j는 , 쓰고, 한 번에 또는 다른에서, 다른 가능성이 없을 것 및 쓰기 B 와 쓰기 . ....

값이 모두 다르면 예를 들어 작성해야합니다.

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'가 다른 객체에 우선적으로 바인딩 되었기 때문에)

나는 10 개의 식별자 a, b, c를 정의하는 유틸리티가 보이지 않기 때문에 False 또는 True를 가리 킵니다. 실행 중에 이러한 값이 변경되지 않으면 왜 10 개의 식별자입니까? 그리고 그들이 변경되면, 왜 식별자를 먼저 정의해야합니까?

네 질문이 이상해 보인다


2

당신이 나에게 잘못된 방법으로 문제에 접근하고있는 것처럼 들립니다.

튜플을 사용하도록 코드를 다시 작성하거나 모든 데이터를 저장하는 클래스를 작성하십시오.


코드를 엿볼 필요조차 없다고 말할 수 있습니다. :) 이것이 이상적이지 않다는 것을 이해하고 다시 포맷해야 할 수도 있지만 대답이 실제로 문제를 해결하지는 않습니다. 그래도 당신의 요점을 알 수 있습니다.
Trufa

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)). 따라서 인덱스를 변경하면 a및 의 인덱스 b가 연결되어 있으므로 인덱스가 모두 변경 됩니다. 이 문제를 해결하려면 (소스)

>> 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에 오신 것을 환영합니다. 답변 주셔서 감사합니다! 다음 질문에 대답 하기 전에 답 을 작성 하십시오.
돼지.

0

JavaScript 와 마찬가지로 파이썬에서 한 줄에 여러 명령문을 사용할 수도 있습니다a = 1; b = "Hello World"; c += 3

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.