비슷한 줄이있는 코드를 보았습니다.
x[x<2]=0
변형을 가지고 놀면서 나는 여전히이 구문이하는 일에 갇혀 있습니다.
예 :
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
비슷한 줄이있는 코드를 보았습니다.
x[x<2]=0
변형을 가지고 놀면서 나는 여전히이 구문이하는 일에 갇혀 있습니다.
예 :
>>> x = [1,2,3,4,5]
>>> x[x<2]
1
>>> x[x<3]
1
>>> x[x>2]
2
>>> x[x<2]=0
>>> x
[0, 2, 3, 4, 5]
TypeError: unorderable types: list() < int()
.
답변:
이것은 NumPy 배열 에서만 의미가 있습니다. . 목록의 동작은 쓸모가 없으며 Python 2 (Python 3 아님)에만 해당됩니다. 원래 객체가 목록이 아니라 실제로 NumPy 배열 (아래 참조)인지 다시 확인하고 싶을 수 있습니다.
그러나 여기 코드에서 x는 간단한 목록입니다.
이후
x < 2
False 즉 0이므로
x[x<2]
이다 x[0]
x[0]
변경됩니다.
반대로, x[x>2]
이다 x[True]
또는x[1]
그래서 x[1]
변경됩니다.
왜 이런 일이 발생합니까?
비교 규칙은 다음과 같습니다.
두 개의 문자열 또는 두 개의 숫자 유형을 주문할 때 순서는 예상 된 방식으로 수행됩니다 (문자열의 사전 순서, 정수의 숫자 순서).
숫자 형과 비숫 자형을 주문하면 숫자 형이 먼저 나옵니다.
둘 다 숫자가 아닌 호환되지 않는 두 가지 유형을 주문하면 유형 이름의 알파벳 순서로 정렬됩니다.
그래서 우리는 다음과 같은 순서를 가지고 있습니다.
숫자 <목록 <문자열 <튜플
Python은 string과 int 를 어떻게 비교합니까?.
x가 NumPy 배열 이면 부울 배열 인덱싱 때문에 구문이 더 의미가 있습니다. 이 경우 x < 2
에는 전혀 부울이 아닙니다. 의 각 요소 x
가 2보다 작은 지 여부를 나타내는 부울 배열입니다 . x[x < 2] = 0
그런 다음 x
2보다 작은 요소를 선택하고 해당 셀을 0으로 설정합니다 . Indexing을 참조하십시오 .
>>> x = np.array([1., -1., -2., 3])
>>> x < 0
array([False, True, True, False], dtype=bool)
>>> x[x < 0] += 20 # All elements < 0 get increased by 20
>>> x
array([ 1., 19., 18., 3.]) # Only elements < 0 are affected
import
numpy를 볼 수 있습니다.
[0 if i < 2 else i for i in x]
.) 아니면 Numpy에서 권장되는 스타일입니까?
x[x<2]
numpy 배열을 [0 if i<2 else i for i in x]
반환하는 반면 목록을 반환합니다. 이는 x[x<2]
인덱싱 작업 (데이터 마스킹 기능으로 인해 numpy / scipy / pandas에서 슬라이싱 작업으로 언급 됨)이지만 목록 이해는 새로운 객체 정의이기 때문입니다. NumPy 인덱싱
>>> x = [1,2,3,4,5]
>>> x<2
False
>>> x[False]
1
>>> x[True]
2
부울은 단순히 정수로 변환됩니다. 인덱스는 0 또는 1입니다.
x<2 == false
있습니까? 이유는 무엇입니까?
bool
정수로 변환되지 않습니다하는 bool
파이썬은 정수입니다
bool
서브 클래스 의 int
.
귀하의 질문에있는 원본 코드는 Python 2에서만 작동합니다. Python 2 에서 x
a list
인 경우 비교 x < y
는 False
if y
가 int
eger입니다. 이는 목록을 정수와 비교하는 것이 의미가 없기 때문입니다. 그러나 Python 2에서 피연산자가 비교할 수없는 경우 비교는 유형 이름의 알파벳 순서 에 따라 CPython을 기반 으로합니다 . 추가적으로 모든 숫자는 혼합 유형 비교에서 첫 번째가됩니다. . 이것은 CPython 2의 문서에도 나와 있지 않으며, 다른 Python 2 구현은 다른 결과를 제공 할 수 있습니다. 즉 [1, 2, 3, 4, 5] < 2
평가 False
하기 때문에 2
숫자와보다 따라서 "작은"입니다 list
CPython을한다. 이 혼합 비교는 결국기능이 너무 모호한 것으로 간주 되어 Python 3.0에서 제거되었습니다.
이제 결과 <
는 다음과 같습니다 bool
. 그리고 bool
A는 서브 클래스 의는int
:
>>> isinstance(False, int)
True
>>> isinstance(True, int)
True
>>> False == 0
True
>>> True == 1
True
>>> False + 5
5
>>> True + 5
6
따라서 기본적으로 비교가 참인지 거짓인지에 따라 요소 0 또는 1을 사용합니다.
Python 3에서 위의 코드를 시도하면 Python 3.0의 변경TypeError: unorderable types: list() < int()
으로 인해 다음과 같은 결과를 얻을 수 있습니다 .
주문 비교
Python 3.0은 순서 비교 규칙을 단순화했습니다.
순서 비교 연산자 (
<
,<=
,>=
,>
) 인상TypeError
피연산자가 의미있는 자연 순서가없는 경우 예외를. 따라서, 표현하고자하지1 < ''
,0 > None
또는len <= len
더 이상 유효하며, 예를None < None
인상TypeError
하는 대신 반환False
. 결과적으로 이기종 목록을 정렬하는 것은 더 이상 의미가 없습니다. 모든 요소는 서로 비교할 수 있어야합니다. 이는==
및!=
연산자 에는 적용되지 않습니다 . 비교할 수없는 다른 유형의 객체는 항상 서로 같지 않은 상태로 비교됩니다.
다른 작업을 수행하기 위해 비교 연산자를 오버로드 하는 많은 데이터 유형이 있습니다 (pandas의 데이터 프레임, numpy의 배열). 사용 중이던 코드가 다른 작업을 수행 한 경우는 이 아니고 연산자 가 아닌 다른 클래스의 인스턴스 가 아닌 값을 반환하도록 재정의 되었기 때문입니다 . 그리고이 값은 (aka / )에 의해 특별히 처리되었습니다.x
list
<
bool
x[]
__getitem__
__setitem__
+False
안녕 Perl, 자바 스크립트, 잘 지내?
UNARY_POSITIVE
부르는 연산 코드__pos__
__setitem__
대신에 의미했다고 생각합니다 __getitem__
. 또한 내 답변이 귀하의 답변에서 영감을 얻은 것에 대해 신경 쓰지 않기를 바랍니다.
__getitem__
하지만 똑같이 수 있었다 __setitem__
과__delitem__
이것은 또 하나의 용도가 있습니다 : 코드 골프. 코드 골프는 가능한 적은 소스 코드 바이트로 문제를 해결하는 프로그램을 작성하는 기술입니다.
return(a,b)[c<d]
대략 다음과 같습니다.
if c < d:
return b
else:
return a
단, a와 b는 첫 번째 버전에서는 평가되지만 두 번째 버전에서는 평가되지 않습니다.
c<d
True
또는로 평가됩니다 False
.
(a, b)
튜플입니다.
튜플에 대한 인덱싱은 목록에 대한 인덱싱처럼 작동합니다 : (3,5)[1]
== 5
.
True
같은지 1
과 False
같다 0
.
(a,b)[c<d]
(a,b)[True]
(a,b)[1]
b
또는 False
:
(a,b)[c<d]
(a,b)[False]
(a,b)[0]
a
스택 교환 네트워크에는 몇 바이트를 절약하기 위해 파이썬에 할 수있는 많은 불쾌한 일에 대한 좋은 목록이 있습니다. /codegolf/54/tips-for-golfing-in-python
일반 코드에서는 절대 사용해서는 안되며, 귀하의 경우 x
에는 정수와 비교할 수있는 것과 매우 특이한 조합 인 슬라이싱을 지원하는 컨테이너 역할을 모두 수행 한다는 것을 의미합니다 . 다른 사람들이 지적했듯이 아마도 Numpy 코드 일 것입니다.
Code Golf is the art of writing programs
: ')
일반적으로 그것은 무엇이든 의미 할 수 있습니다 . 이미 있다면 그것이 무엇을 의미하는지 설명 x
A는 list
또는 numpy.ndarray
그러나 일반적으로 만 비교 연산자 (방법에 따라 달라집니다 <
, >
...) 그리고이 또한 GET / SET-항목 (어떻게 [...]
- 구문) 구현됩니다.
x.__getitem__(x.__lt__(2)) # this is what x[x < 2] means!
x.__setitem__(x.__lt__(2), 0) # this is what x[x < 2] = 0 means!
때문에:
x < value
다음과 같다 x.__lt__(value)
x[value]
(대략) x.__getitem__(value)
x[value] = othervalue
는 (대략) x.__setitem__(value, othervalue)
.원하는 모든 작업을 수행하도록 사용자 지정할 수 있습니다 . 예를 들어 (약간 numpys-boolean 인덱싱을 모방 함) :
class Test:
def __init__(self, value):
self.value = value
def __lt__(self, other):
# You could do anything in here. For example create a new list indicating if that
# element is less than the other value
res = [item < other for item in self.value]
return self.__class__(res)
def __repr__(self):
return '{0} ({1})'.format(self.__class__.__name__, self.value)
def __getitem__(self, item):
# If you index with an instance of this class use "boolean-indexing"
if isinstance(item, Test):
res = self.__class__([i for i, index in zip(self.value, item) if index])
return res
# Something else was given just try to use it on the value
return self.value[item]
def __setitem__(self, item, value):
if isinstance(item, Test):
self.value = [i if not index else value for i, index in zip(self.value, item)]
else:
self.value[item] = value
이제 사용하면 어떻게되는지 보겠습니다.
>>> a = Test([1,2,3])
>>> a
Test ([1, 2, 3])
>>> a < 2 # calls __lt__
Test ([True, False, False])
>>> a[Test([True, False, False])] # calls __getitem__
Test ([1])
>>> a[a < 2] # or short form
Test ([1])
>>> a[a < 2] = 0 # calls __setitem__
>>> a
Test ([0, 2, 3])
이것은 하나의 가능성 일뿐입니다. 원하는 거의 모든 것을 자유롭게 구현할 수 있습니다.