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

“동시”에 여러 변수를 선언하려면 다음을 수행하십시오.

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

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



답변

다른 사람들이 제안했듯이 부울 값과 함께 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 모듈 의 일부 기능을 결합 할 수도 있습니다 . 그들이 말하는 것처럼, 한 가지 이상의 방법이 있습니다. 잠깐, 파이썬 사람들은 그렇게 말하지 않습니다. 어쨌든 그것은 사실입니다. 귀도는 우리에게 사전 이해력을 주어서 이것을 할 수있는 분명한 방법 이있을 것이라고 생각합니다.


답변

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


답변

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

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


답변

이것은 @ 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))


답변

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

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

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”와 알파벳 문자보다 더 의미있는 이름을 사용하기를 희망합니다.


답변

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

당신이 정말로 필요하거나 원하는 경우 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 개의 식별자입니까? 그리고 그들이 변경되면, 왜 식별자를 먼저 정의해야합니까?

네 질문이 이상해 보인다


답변

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

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