값에 대해 여러 변수를 테스트하는 방법은 무엇입니까?


644

여러 변수를 정수와 비교하고 세 글자의 문자열을 출력하는 함수를 만들려고합니다. 이것을 파이썬으로 번역하는 방법이 있는지 궁금합니다. 이렇게 말하십시오 :

x = 0
y = 1
z = 3
mylist = []

if x or y or z == 0 :
    mylist.append("c")
if x or y or z == 1 :
    mylist.append("d")
if x or y or z == 2 :
    mylist.append("e")
if x or y or z == 3 : 
    mylist.append("f")

다음 목록을 반환합니다.

["c", "d", "f"]

이와 같은 것이 가능합니까?


5
사용 1(튜플)

2
문장 목록을 어떤 방식 으로든 평가하려는 경우 any/ all함수를 사용할 수 있습니다 . 예를 들어 : all([1, 2, 3, 4, False])False all([True, 1, 2, 3])를 반환합니다. True any([False, 0, 0, False])를 반환합니다. False any([False, 0, True, False])를 반환합니다.
eddd

4
이 질문은 매우 인기있는 복제 대상이지만 그 목적에 적합하지 않다고 생각합니다. 대부분의 사람들은와 if x == 0 or 1:비슷한 것을 시도 if x or y == 0:하지만 초보자에게는 약간 혼란 스러울 수 있습니다. 의 엄청난 양을 감안할 때 "왜없는 x == 0 or 1작업?" 질문에 대해서는 이 질문이 질문 에 대한 정식 복제 대상으로 사용하는 것이 좋습니다 .
Aran-Fey

1
같은 "falsey"값을 비교할 때 좀 더주의를 기울여 0, 0.0또는 False. "올바른"답변을 제공하는 잘못된 코드를 쉽게 작성할 수 있습니다.
smci

답변:


850

부울 표현식의 작동 방식을 오해합니다. 그들은 영어 문장처럼 작동하지 않으며 여기에서 모든 이름에 대해 동일한 비교에 대해 이야기하고 있다고 생각합니다. 당신이 찾고있는:

if x == 1 or y == 1 or z == 1:

x그리고 y그렇지 않으면 (스스로 평가 False하는 경우 0, True기타).

튜플 에 대해 포함 테스트를 사용하면 단축 할 수 있습니다 .

if 1 in (x, y, z):

또는 더 나은 방법 :

if 1 in {x, y, z}:

aset 를 사용하여 일정 비용 멤버쉽 테스트를 활용하십시오 ( in왼쪽 피연산자가 무엇이든 고정 된 시간이 걸립니다).

을 사용 or하면 파이썬은 연산자의 각면을 별도의 표현식 으로 간주 합니다. 표현식 x or y == 1은에 대한 부울 테스트로 먼저 처리 된 x다음 False 인 경우 표현식 y == 1이 테스트됩니다.

이것은 운영자 우선 순위 때문 입니다. or작업자는보다 낮은 우선 갖는 ==후자 평가되도록, 시험 .

그러나 이것이 사실이 아니고 표현식 x or y or z == 1이 실제로 (x or y or z) == 1대신 해석 된 경우에도 예상 한대로 수행되지 않습니다.

x or y or zFalse숫자가 0이거나 비어있는 'truthy'인 첫 번째 인수로 평가합니다 ( 부울 컨텍스트에서 Python이 false로 간주하는 것에 대한 자세한 내용 은 부울 표현식 참조 ).

따라서 가치 x = 2; y = 1; z = 0 , x or y or z에 해결하는 것 2즉 인수의 최초의 진정한 같은 값이기 때문입니다. 그런 2 == 1False, 비록 y == 1것이다 True.

반대의 경우도 마찬가지입니다. 단일 변수에 대해 여러 값을 테스트하는 단계; x == 1 or 2 or 3같은 이유로 실패합니다. 사용하다x == 1 or x == 2 or x == 3또는을x in {1, 2, 3} .


116
나는 set버전에 너무 빨리 가지 않을 것 입니다. 튜플은 작성 및 반복이 매우 저렴합니다. 내 컴퓨터에서 적어도 튜플의 크기가 약 4-8 요소 인 한 튜플은 세트보다 빠릅니다. 그 이상을 스캔해야한다면 세트를 사용하되, 2-4 개의 가능성 중 하나를 찾고 있다면 튜플이 더 빠릅니다! 당신이 튜플의 첫째 될 가능성이 가장 높은 경우를 준비 할 수 있다면, 승리는 더 큰 것입니다 : (내 테스트 : timeit.timeit('0 in {seq}'.format(seq=tuple(range(9, -1, -1)))))
SingleNegationElimination

57
@dequestarmappartialsetattr : Python 3.3 이상에서는 생성 시간을 완전히 무시하고 생성 시간을 없애고 상수로 저장됩니다. 튜플 메모리 변동을 피하기 위해 파이썬이 번들을 캐시 때 저렴할 있습니다.
Martijn Pieters

13
@dequestarmappartialsetattr : 멤버쉽 테스트 시간 정하면 이상적인 시나리오에 대해 정수 세트와 튜플의 속도가 동일합니다. 첫 번째 요소와 일치합니다. 그 후 튜플은 세트를 잃습니다.
Martijn Pieters

17
@MartijnPieters : set이 테스트에 리터럴 표기법을 사용하면 리터럴의 내용이 set리터럴 이 아닌 한 절약되지 않습니다 . if 1 in {x, y, z}:를 캐시 할 수 set있기 때문에 x, y그리고 z두 솔루션의 요구가 구축 할 수 있도록 변경 될 수 있습니다 tuple또는 set처음부터, 그리고 나는 회원 확인이 더에 의해 압도 될 때 당신이 얻을 수있는 절감 조회 어떤 의심 set생성 시간을.
ShadowRanger

9
@ShadowRanger : 예, 들여다 보는 구멍 최적화 ( in [...]또는로 in {...})는 목록 또는 세트의 내용이 변경 불가능한 리터럴 인 경우에만 작동합니다.
Martijn Pieters

96

다음과 같은 사전 구조로 문제를보다 쉽게 ​​해결할 수 있습니다.

x = 0
y = 1
z = 3
d = {0: 'c', 1:'d', 2:'e', 3:'f'}
mylist = [d[k] for k in [x, y, z]]

21
또는 심지어 다음 d = "cdef"으로 이어집니다MyList = ["cdef"[k] for k in [x, y, z]]
aragaer

9
또는map(lambda i: 'cdef'[i], [x, y, z])
dansalmo

3
@MJM 출력 순서는 dict에 의해 결정되지 않습니다, 그것은 목록의 순서에 의해 결정됩니다[x, y, z]
dansalmo

1
내가 아직 완전히 익숙하지 않은 목록 이해를 제외하고, 우리 대부분은 같은 반사를 가졌습니다.
LoneWanderer

66

Martijn Pieters가 말했듯이 정확하고 빠른 형식은 다음과 같습니다.

if 1 in {x, y, z}:

지금 전이었다 여부를 파이썬 각 문장을 읽을 것을 별도의 경우 명령문 그렇게했을 그의 조언을 사용 True하거나 False. 같은 :

if 0 in {x, y, z}:
    mylist.append("c")
if 1 in {x, y, z}:
    mylist.append("d")
if 2 in {x, y, z}:
    mylist.append("e")
...

이것은 효과가 있지만 사전을 사용하는 것이 편 하다면 (내가 한 일을 참조하십시오) 숫자를 원하는 문자에 매핑 한 다음 for 루프를 사용하여 초기 사전을 만들어 정리할 수 있습니다.

num_to_letters = {0: "c", 1: "d", 2: "e", 3: "f"}
for number in num_to_letters:
    if number in {x, y, z}:
        mylist.append(num_to_letters[number])

45

직접 쓰는 방법 x or y or z == 0

if any(map((lambda value: value == 0), (x,y,z))):
    pass # write your logic.

그러나 나는 당신이 그것을 좋아한다고 생각하지 않습니다. :) 그리고이 방법은 못생긴입니다.

다른 방법 (더 나은)은 다음과 같습니다.

0 in (x, y, z)

BTW ifs는 다음과 같이 쓸 수 있습니다.

my_cases = {
    0: Mylist.append("c"),
    1: Mylist.append("d")
    # ..
}

for key in my_cases:
    if key in (x,y,z):
        my_cases[key]()
        break

8
dict키 대신에 대한 예제에서는 .appendis 의 반환 값 None이고 호출 None하면을 제공 하기 때문에 오류가 발생 합니다 AttributeError. 일반적으로 나는이 방법에 동의합니다.
SethMMorton

2
키 대신 dict가 잘못되면 "for..loop"부분을 주석 처리해도 사전이 초기화 될 때 Mylist = [ 'c', 'd']가 표시됩니다.
Mahmoud Elshahat

1
람다가 true로 평가되는 인스턴스 만 반환하므로 첫 번째 예에서는 filter보다 낫습니다 map.
Alex

1
이해는 람다의지도보다 훨씬 간단합니다.any(v == 0 for v in (x, y, z))
wjandrea

35

매우 게으른 경우 값을 배열 안에 넣을 수 있습니다. 와 같은

list = []
list.append(x)
list.append(y)
list.append(z)
nums = [add numbers here]
letters = [add corresponding letters here]
for index in range(len(nums)):
    for obj in list:
        if obj == num[index]:
            MyList.append(letters[index])
            break

숫자와 문자를 사전에 넣어서 할 수도 있지만 이것은 아마도 if 문보다 훨씬 더 복잡 할 것입니다. 그것은 당신이 여분의 게 으르려고 노력하면서 얻는 것입니다 :)

한가지 더

if x or y or z == 0:

컴파일하지만 원하는 방식으로 컴파일하지는 않습니다. if 문에 변수를 넣을 때 (예)

if b

프로그램은 변수가 null이 아닌지 확인합니다. 위의 진술을 작성하는 또 다른 방법은 (더 의미가 있습니다)

if bool(b)

Bool은 기본적으로 boolean 문을 확인하는 명령을 수행하는 Python의 기본 제공 함수입니다 (무엇이 무엇인지 모르는 경우 if 문에서 바로 만들려고합니다 :))

내가 찾은 또 다른 게으른 방법은 다음과 같습니다.

if any([x==0, y==0, z==0])

3
-1 여기에는 많은 연습이 있습니다. list파이썬 내장입니다; xyz예를 들어 다른 이름을 대신 사용하십시오 . 왜 할 수있을 때 왜 네 단계로 목록을 구성 xyz = [x, y, z]합니까? 병렬 목록을 사용하지 말고 대신 dict를 사용하십시오. 대체로이 솔루션은 ThatGuyRussell의 솔루션보다 훨씬 복잡 합니다. 또한 마지막 부분에 대해 왜 이해를하지 any(v == 0 for v in (x, y, z))않습니까? 또한 배열 은 파이썬에서 다른 것입니다.
wjandrea

32

변수 집합 내에 값이 포함되어 있는지 확인하려면 내장 모듈 itertools및을 사용할 수 있습니다 operator.

예를 들면 다음과 같습니다.

수입품 :

from itertools import repeat
from operator import contains

변수 선언 :

x = 0
y = 1
z = 3

확인하려는 순서대로 값의 맵핑을 작성하십시오.

check_values = (0, 1, 3)

itertools변수 반복을 허용하는 데 사용하십시오 .

check_vars = repeat((x, y, z))

마지막으로 map함수를 사용하여 반복자를 만듭니다.

checker = map(contains, check_vars, check_values)

그런 다음 원래 순서대로 값을 확인할 때 다음을 사용하십시오 next().

if next(checker)  # Checks for 0
    # Do something
    pass
elif next(checker)  # Checks for 1
    # Do something
    pass

기타...

내장 모듈 lambda x: x in (variables)이기 때문에 operator사용하는 것보다 빠르고 효율적 이기 때문에 이점이 있습니다.lambda 사용자 정의 위치 내 기능을 작성하는 .

목록에 0이 아닌 값 (또는 False)이 있는지 확인하는 또 다른 옵션 :

not (x and y and z)

동등한:

not all((x, y, z))

2
이것은 OP의 질문에 대답하지 않습니다. 제공된 예제의 첫 번째 경우 만 다룹니다.
wallacer 2016 년

31

변수를 주문하기 때문에 여기에 목표가있는 것 같습니다. {z,y,x}{0,1,3}매개 변수의 어떤 순서.

>>> ["cdef"[i] for i in {z,x,y}]
['c', 'd', 'f']

이런 식으로 전체 솔루션은 O (n)입니다.


5
코드가 수행하는 작업과 수행 방법에 대한 설명을 추가해야합니다. 코드 만 사용하는 짧은 답변은 권장하지 않습니다
Raniz

31

여기에 제공된 모든 훌륭한 답변은 원본 포스터의 특정 요구 사항에 집중 if 1 in {x,y,z}하고 Martijn Pieters가 제시 한 솔루션에 집중합니다 .
그들이 무시하는 것은 질문의 광범위한 의미입니다.
여러 값에 대해 하나의 변수를 어떻게 테스트합니까?
문자열을 사용하는 경우 제공된 솔루션이 부분 적중에 대해 작동하지 않습니다. 예를 들어
문자열 "Wild"가 여러 값인지 확인하십시오.

>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in {x, y, z}: print (True)
... 

또는

>>> x = "Wild things"
>>> y = "throttle it back"
>>> z = "in the beginning"
>>> if "Wild" in [x, y, z]: print (True)
... 

이 시나리오에서는 문자열로 변환하는 것이 가장 쉽습니다.

>>> [x, y, z]
['Wild things', 'throttle it back', 'in the beginning']
>>> {x, y, z}
{'in the beginning', 'throttle it back', 'Wild things'}
>>> 

>>> if "Wild" in str([x, y, z]): print (True)
... 
True
>>> if "Wild" in str({x, y, z}): print (True)
... 
True

그러나에서 언급했듯이 @codeforester단어 경계는이 방법으로 다음과 같이 손실됩니다.

>>> x=['Wild things', 'throttle it back', 'in the beginning']
>>> if "rot" in str(x): print(True)
... 
True

세 글자 rot는 목록에 조합되어 있지만 개별 단어 로 는 존재하지 않습니다. "rot"에 대한 테스트는 실패하지만 목록 항목 중 하나가 "hell in hell"인 경우에도 실패합니다.
결과적으로이 방법을 사용하는 경우 검색 기준에주의하고이 제한이 있음을 알고 있어야합니다.


30

나는 이것이 더 잘 처리 할 것이라고 생각한다.

my_dict = {0: "c", 1: "d", 2: "e", 3: "f"}

def validate(x, y, z):
    for ele in [x, y, z]:
        if ele in my_dict.keys():
            return my_dict[ele]

산출:

print validate(0, 8, 9)
c
print validate(9, 8, 9)
None
print validate(9, 8, 2)
e

30

if를 사용하려는 경우 else 다음 명령문은 다른 솔루션입니다.

myList = []
aList = [0, 1, 3]

for l in aList:
    if l==0: myList.append('c')
    elif l==1: myList.append('d')
    elif l==2: myList.append('e')
    elif l==3: myList.append('f')

print(myList)

26
d = {0:'c', 1:'d', 2:'e', 3: 'f'}
x, y, z = (0, 1, 3)
print [v for (k,v) in d.items() if x==k or y==k or z==k]

26

이 코드는 도움이 될 수 있습니다

L ={x, y, z}
T= ((0,"c"),(1,"d"),(2,"e"),(3,"f"),)
List2=[]
for t in T :
if t[0] in L :
    List2.append(t[1])
    break;

12

아래 표시된 방법을 시도 할 수 있습니다. 이 방법에서는 입력하고자하는 변수의 수를 자유롭게 지정 / 입력 할 수 있습니다.

mydict = {0:"c", 1:"d", 2:"e", 3:"f"}
mylist= []

num_var = int(raw_input("How many variables? ")) #Enter 3 when asked for input.

for i in range(num_var): 
    ''' Enter 0 as first input, 1 as second input and 3 as third input.'''
    globals()['var'+str('i').zfill(3)] = int(raw_input("Enter an integer between 0 and 3 "))
    mylist += mydict[globals()['var'+str('i').zfill(3)]]

print mylist
>>> ['c', 'd', 'f']

10

한 줄 솔루션 :

mylist = [{0: 'c', 1: 'd', 2: 'e', 3: 'f'}[i] for i in [0, 1, 2, 3] if i in (x, y, z)]

또는:

mylist = ['cdef'[i] for i in range(4) if i in (x, y, z)]

9

출력 비트 세트에 대한 직접적인 공식이 필요할 수 있습니다.

x=0 or y=0 or z=0   is equivalent to x*y*z = 0

x=1 or y=1 or z=1   is equivalent to (x-1)*(y-1)*(z-1)=0

x=2 or y=2 or z=2   is equivalent to (x-2)*(y-2)*(z-2)=0

비트에 매핑하자 : 'c':1 'd':0xb10 'e':0xb100 'f':0xb1000

isc의 관계 ( 'c') :

if xyz=0 then isc=1 else isc=0

수식 https://youtu.be/KAdKCgBGK0k?list=PLnI9xbPdZUAmUL8htSl6vToPQRRN3hhFp&t=315 인 경우 수학 사용

[씨]: (xyz=0 and isc=1) or (((xyz=0 and isc=1) or (isc=0)) and (isc=0))

[디]: ((x-1)(y-1)(z-1)=0 and isc=2) or (((xyz=0 and isd=2) or (isc=0)) and (isc=0))

...

다음 논리에 따라이 공식을 연결하십시오.

  • 논리 and는 방정식의 제곱의 합입니다
  • 논리 or는 방정식의 곱입니다

그리고 당신은 총 방정식 표현 합계를 가지고 당신은 합계의 공식을 가지고

sum & 1은 c, sum & 2는 d, sum & 4는 e, sum & 5는 f

그런 다음 문자열 요소의 색인이 준비된 문자열에 해당하는 사전 정의 된 배열을 형성 할 수 있습니다.

array[sum] 당신에게 문자열을 제공합니다.


7

그것은 쉽게 할 수 있습니다

for value in [var1,var2,var3]:
     li.append("targetValue")

6

파이썬에서 의사 코드를 표현하는 가장 니모닉 방식은 다음과 같습니다.

x = 0
y = 1
z = 3
mylist = []

if any(v == 0 for v in (x, y, z)):
    mylist.append("c")
if any(v == 1 for v in (x, y, z)):
    mylist.append("d")
if any(v == 2 for v in (x, y, z)):
    mylist.append("e")
if any(v == 3 for v in (x, y, z)):
    mylist.append("f")

1
이 접근 방식은 임의의 비교 (예 :)를 허용하기 때문에`2 in (x, y, z) : mylist.append ( 'e')보다 보편적 if any(v >= 42 for v in (x, y, z)):입니다. 그리고 3 가지 방법의 성능 ( 2 in {x,y,z}, 2 in (x,y,z), any(_v == 2 for _v in (x,y,z))) CPython3.6에서 거의 같은 것으로 보인다 (참조 요점을 )
imposeren

5

하나의 단일 값으로 여러 변수를 테스트하려면 if 1 in {a,b,c}:

하나의 변수로 여러 값을 테스트하려면 if a in {1, 2, 3}:


4

일종의 시저 암호를 작성하는 것 같습니다.

훨씬 더 일반적인 접근 방식은 다음과 같습니다.

input_values = (0, 1, 3)
origo = ord('c')
[chr(val + origo) for val in inputs]

출력

['c', 'd', 'f']

그것이 코드의 원하는 부작용인지 확실하지 않지만 출력 순서는 항상 정렬됩니다.

이것이 원하는 경우 마지막 줄을 다음과 같이 변경할 수 있습니다.

sorted([chr(val + origo) for val in inputs])

2

당신은 사전을 사용할 수 있습니다 :

x = 0
y = 1
z = 3
list=[]
dict = {0: 'c', 1: 'd', 2: 'e', 3: 'f'}
if x in dict:
    list.append(dict[x])
else:
    pass

if y in dict:
    list.append(dict[y])
else:
    pass
if z in dict:
    list.append(dict[z])
else:
    pass

print list

1
이것은 이것에 한번 더 추가 될 수 있습니다. 세트?
Sergei

2

dict 없이이 솔루션을 사용해보십시오.

x, y, z = 0, 1, 3    
offset = ord('c')
[chr(i + offset) for i in (x,y,z)]

그리고 제공합니다 :

['c', 'd', 'f']

0

도움이 될 것입니다.

def test_fun(val):
    x = 0
    y = 1
    z = 2
    myList = []
    if val in (x, y, z) and val == 0:
        myList.append("C")
    if val in (x, y, z) and val == 1:
        myList.append("D")
    if val in (x, y, z) and val == 2:
        myList.append("E")

test_fun(2);

0

당신은 이것을 묶을 수 있습니다

x = 0
y = 1
z = 3

하나의 변수로.

In [1]: xyz = (0,1,3,) 
In [2]: mylist = []

다음과 같이 조건을 변경하십시오.

In [3]: if 0 in xyz: 
    ...:     mylist.append("c") 
    ...: if 1 in xyz: 
    ...:     mylist.append("d") 
    ...: if 2 in xyz: 
    ...:     mylist.append("e") 
    ...: if 3 in xyz:  
    ...:     mylist.append("f") 

산출:

In [21]: mylist                                                                                
Out[21]: ['c', 'd', 'f']

0

문제

여러 값을 테스트하기위한 패턴

>>> 2 in {1, 2, 3}
True
>>> 5 in {1, 2, 3}
False

매우 읽기 쉽고 많은 상황에서 작동하고 있습니다. 하나의 함정이 있습니다.

>>> 0 in {True, False}
True

하지만 우리는 갖고 싶어

>>> (0 is True) or (0 is False)
False

해결책

이전 표현의 일반화는 ytpillai 의 답변을 기반으로합니다 .

>>> any([0 is True, 0 is False])
False

이것은 다음과 같이 쓸 수 있습니다

>>> any(0 is item for item in (True, False))
False

이 표현식은 올바른 결과를 반환하지만 첫 번째 표현식만큼 읽을 수 없습니다 :-(

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