1이 뭔데?__truediv__`?><<<<<python>>>><<<<python>>><<<python>>
최근 파이썬을 배울 때나 대부분의 튜토리얼에서 본 적이 없는 구문을 접하게 되었다...
표기법, 이것과 비슷한 것 같다.
f = 1..__truediv__ # or 1..__div__ for python 2
print(f(8)) # prints 0.125
나는 그것이 (물론 더 길다는 것 빼고는) 정확히 똑같다고 생각했다.
f = lambda x: (1).__truediv__(x)
print(f(8)) # prints 0.125 or 1//8
하지만 내 질문은:
- 어떻게 된 일일까요?
- 이 두 개의 점이 실제로 의미하는 것은 무엇인가?
- 어떻게 하면 좀 더 복잡한 문장으로 (가능하면) 쓸 수 있을까?
이렇게 하면 앞으로 코드 라인이 많이 절약될 겁니다...:)
당신이 가지고 있는 것은float
후행 0이 없는 리터럴을 사용하면__truediv__
의 방법.그것은 그 자체로 연산자가 아니다; 첫 번째 점은 플로트 값의 일부분이고, 두 번째 점은 물체 속성과 메서드에 접근하는 점 연산자다.
다음과 같이 하면 같은 경지에 도달할 수 있다.
>>> f = 1.
>>> f
1.0
>>> f.__floordiv__
<method-wrapper '__floordiv__' of float object at 0x7f9fb4dc1a20>
다른 예
>>> 1..__add__(2.)
3.0
여기 1.0에 2.0을 추가하면 3.0이 나온다.
그 문제는 이미 충분히 답변되어 있지만(즉, @Paul Rooney의 대답) 이러한 답변의 정확성을 검증하는 것도 가능하다.
기존 답변을 다시 요약해 봅시다.그..
단일 구문 요소가 아니다!
소스 코드가 어떻게 "토큰" 상태인지 확인할 수 있다.이러한 토큰은 코드가 해석되는 방식을 나타낸다.
>>> from tokenize import tokenize
>>> from io import BytesIO
>>> s = "1..__truediv__"
>>> list(tokenize(BytesIO(s.encode('utf-8')).readline))
[...
TokenInfo(type=2 (NUMBER), string='1.', start=(1, 0), end=(1, 2), line='1..__truediv__'),
TokenInfo(type=53 (OP), string='.', start=(1, 2), end=(1, 3), line='1..__truediv__'),
TokenInfo(type=1 (NAME), string='__truediv__', start=(1, 3), end=(1, 14), line='1..__truediv__'),
...]
그래서 끈은1.
숫자로 해석되며, 두 번째 숫자로 해석된다..
OP( 연산자, 이 경우 "get attribute" 연산자) 및__truediv__
메서드 이름이다.그럼 이건 그냥 접근하는거야__truediv__
부유식 방법1.0
.
생성된 바이트코드를 보는 또 다른 방법은 그것을 조립하는 것이다.이는 실제로 일부 코드가 실행될 때 수행되는 지침을 보여준다.
>>> import dis
>>> def f():
... return 1..__truediv__
>>> dis.dis(f)
4 0 LOAD_CONST 1 (1.0)
3 LOAD_ATTR 0 (__truediv__)
6 RETURN_VALUE
그건 기본적으로 똑같아.속성을 로드한다.__truediv__
상수의1.0
.
당신의 질문에 관하여
그리고 어떻게 하면 좀 더 복잡한 문장으로 (가능한 경우) 사용할 수 있을까?
비록 그렇게 코드를 쓰면 안 된다 하더라도, 단지 코드가 무엇을 하고 있는지 불명확하기 때문에.그러니 제발 좀 더 복잡한 진술에 쓰지 말아줘.나는 심지어 당신이 그렇게 "단순한" 문장에 그것을 사용해서는 안 될 정도로까지 할 것이다. 적어도 지시사항을 분리하기 위해서는 괄호를 사용해야 한다.
f = (1.).__truediv__
이것은 확실히 더 읽기 쉬울 것이다 - 그러나 다음과 같은 선에 따른 것이다.
from functools import partial
from operator import truediv
f = partial(truediv, 1.0)
더 좋을 거야!
접근 방법을 :partial
또한 python의 데이터 모델(The)도 보존한다.1..__truediv__
접근은 그렇지 않다!) 이 작은 조각에 의해 증명될 수 있는 것은:
>>> f1 = 1..__truediv__
>>> f2 = partial(truediv, 1.)
>>> f2(1+2j) # reciprocal of complex number - works
(0.2-0.4j)
>>> f2('a') # reciprocal of string should raise an exception
TypeError: unsupported operand type(s) for /: 'float' and 'str'
>>> f1(1+2j) # reciprocal of complex number - works but gives an unexpected result
NotImplemented
>>> f1('a') # reciprocal of string should raise an exception but it doesn't
NotImplemented
왜하하면 되기 때문이다.1. / (1+2j)
평가되지 않음float.__truediv__
을 가지고는complex.__rtruediv__
-operator.truediv
정상 작동이 반환될 때 역방향 작동이 호출되는지 확인NotImplemented
이 하만지망 수표 을 할 이 없다__truediv__
道의 의 상실이 안 이유다이러한 "기대된 행동"의 상실은 당신이 (보통) 마술적인 방법을 직접 사용해서는 안 되는 주된 이유다.
두 개의 점이 함께 있으면 처음에는 좀 어색할 수 있다.
f = 1..__truediv__ # or 1..__div__ for python 2
그러나 그것은 다음과 같은 글을 쓰는 것과 같다.
f = 1.0.__truediv__ # or 1.0.__div__ for python 2
왜냐하면float
리터럴은 다음과 같은 세 가지 형태로 쓸 수 있다.
normal_float = 1.0
short_float = 1. # == 1.0
prefixed_float = .1 # == 0.1
뭐가
f = 1..__truediv__
?
f
1의 값을 가진 플로트의 바인딩된 특수 방법이다.구체적으로 말하자면
1.0 / x
Python 3에서 다음을 호출한다.
(1.0).__truediv__(x)
증거:
class Float(float):
def __truediv__(self, other):
print('__truediv__ called')
return super(Float, self).__truediv__(other)
및:
>>> one = Float(1)
>>> one/2
__truediv__ called
0.5
다음 작업을 수행하는 경우:
f = one.__truediv__
우리는 그 바인딩된 방법에 대한 이름을 가지고 있다.
>>> f(2)
__truediv__ called
0.5
>>> f(3)
__truediv__ called
0.3333333333333333
만약 우리가 그 점묘법을 빠듯하게 반복한다면, 이것은 시간을 조금 절약할 수 있을 것이다.
AST(추상 구문 트리) 구문 분석
우리는 AST를 그 표현에 대해 구문 분석하는 것은 우리가 그 표현을 얻고 있다는 것을 말해준다는 것을 알 수 있다.__truediv__
속성은, 부동 수긍의 속성,1.0
:
>>> import ast
>>> ast.dump(ast.parse('1..__truediv__').body[0])
"Expr(value=Attribute(value=Num(n=1.0), attr='__truediv__', ctx=Load()))"
다음과 같은 결과 기능을 사용할 수 있다.
f = float(1).__truediv__
아니면
f = (1.0).__truediv__
공제
우리는 또한 추론을 통해 그곳에 도달할 수 있다.
그것을 쌓자.
1은 그 자체로int
:
>>> 1
1
>>> type(1)
<type 'int'>
1이 플로트된 후 마침표가 있는 경우:
>>> 1.
1.0
>>> type(1.)
<type 'float'>
다음 점 자체는 구문 오류일 수 있지만 플로트의 인스턴스(instance)에서 점 조회를 시작한다.
>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>
아무도 이것에 대해 언급하지 않았다 - 이것은 이제 플로트에서 "바운드 방식"이다.1.0
:
>>> f = 1..__truediv__
>>> f
<method-wrapper '__truediv__' of float object at 0x127F3CD8>
>>> f(2)
0.5
>>> f(3)
0.33333333333333331
우리는 같은 기능을 훨씬 더 읽기 쉽게 수행할 수 있었다.
>>> def divide_one_by(x):
... return 1.0/x
...
>>> divide_one_by(2)
0.5
>>> divide_one_by(3)
0.33333333333333331
퍼포먼스
.divide_one_by
함수는 다른 Python 스택 프레임을 요구하여 바운드 방법보다 다소 느리게 만드는 것이다.
>>> def f_1():
... for x in range(1, 11):
... f(x)
...
>>> def f_2():
... for x in range(1, 11):
... divide_one_by(x)
...
>>> timeit.repeat(f_1)
[2.5495760687176485, 2.5585621018805469, 2.5411816588331888]
>>> timeit.repeat(f_2)
[3.479687248616699, 3.46196088706062, 3.473726342237768]
물론, 만약 여러분이 평범한 리터럴을 사용할 수 있다면, 그것은 훨씬 더 빠르다.
>>> def f_3():
... for x in range(1, 11):
... 1.0/x
...
>>> timeit.repeat(f_3)
[2.1224895628296281, 2.1219930218637728, 2.1280188256941983]
'programing' 카테고리의 다른 글
Vuetify : 스로틀/차단 v-autocomplete (0) | 2022.03.28 |
---|---|
Radium 플러그인 사용 시 정의되지 않은 오류의 reactJs styleKeeperContext'를 가져오는 중 (0) | 2022.03.28 |
useState가 계속 초기값으로 재설정됨재렌더 시 (0) | 2022.03.28 |
VueJS 2에서 v-for 값 + 문자열을 사용하는 동적 v-모델 (0) | 2022.03.28 |
Resact Native가 Windows(윈도우)에서 개발을 지원하지 않는가? (0) | 2022.03.28 |