`1 ..__ truediv__`는 무엇입니까? 파이썬에는 .. ( "dot dot") 표기법 구문이 있습니까?


190

나는 최근에 파이썬을 배울 때 보지 못했던 구문이나 대부분의 자습서에서 ..표기법을 보았습니다 .

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

그러나 내 질문은 :

  • 어떻게 할 수 있습니까?
  • 두 점에서 실제로 무엇을 의미합니까?
  • 더 복잡한 문장에서 어떻게 사용할 수 있습니까 (가능한 경우)?

이것은 아마도 나에게 많은 코드 줄을 저장할 것입니다 ... :)


14
참고 : 이전 호출과는 달리 이전 호출과 (1).__truediv__동일 하지 않습니다 . 또는 (공백과 함께)`1..__truediv__int.__truediv__float.__truediv__1 .__truediv__
tobias_k

7
참고 1//8입니다 0하지, 0.125파이썬의 두 버전에서.
mkrieger1

1
생각 나게if (x <- 3) {...}
Dunno

7
다음 은 사용중인 예입니다.
Éamonn Olive

3
@KeithC 고품질의 답변과 의견은 샘플 코드가 이해하는 데 필요한 통찰력이 필요하고, 많은 사람들에게 놀랍고, 더 명확하고 더 일반적이며 최소한 효율적인 대안이 있음을 보여줍니다. 내 주된 어려움은 가독성이 중요하다는 것입니다. 가장 필요한 곳에 대한 영리함을 유지하십시오-인간과의 의사 소통.
피터 우드

답변:


212

당신이 가진 것은 float후행 0이없는 리터럴이며, 그런 다음 __truediv__메소드에 액세스합니다 . 그 자체로는 연산자가 아닙니다. 첫 번째 점은 float 값의 일부이고 두 번째 점은 객체 속성 및 메서드에 액세스하는 점 연산자입니다.

다음을 수행하여 동일한 지점에 도달 할 수 있습니다.

>>> 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이됩니다.


165
우리가 찾은 것은 약간의 간결함을 위해 많은 명확성을 희생 한 개발자입니다.
TemporalWolf

11
어쩌면 누군가가 5.5 "플로피 디스크에 소스 코드를 저장하고 있습니까?
Thomas Ayoub

10
@ThomasAyoub 5.25 "일 것입니다. iirc ;-)
jjmontes

9
@TemporalWolf 그는 최근 코드 골프 제출 에서 그것을 발견했을 것입니다 .
Brian McCutchon

2
재미있는 사실은 JavaScript로도 가능합니다 :1..toString()
Derek 朕 會 功夫

74

질문은 이미 충분히 답변 되었지만 (예 : @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 속성"연산자)이고 __truediv__메소드 이름입니다. 그래서 이것은 단지 __truediv__float 메소드에 접근하고 1.0있습니다.

생성 된 바이트 코드를 보는 또 다른 방법은이를 조립 하는 것입니다. 이것은 실제로 일부 코드가 실행될 때 수행되는 명령을 보여줍니다. dis

>>> 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 유지 합니다 ( 접근법은 아닙니다!).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하지만, 당신이 작동 할 때이 폴백 (fallback)가없는 __truediv__직접. 이러한 "예상 된 행동"의 상실은 (일반적으로) 마술 방법을 직접 사용해서는 안되는 주된 이유입니다.


40

처음에는 두 개의 점이 약간 어색 할 수 있습니다.

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

놀랍습니다. 왜 이러한 유효한 구문 1.__truediv__이 아닌가?
Alex Hall

3
@AlexHall 여기를 참조 하십시오 . 은 .숫자의 일부로서 해석되는 것으로 보인다 다음 .방법에 대한 접근이 없습니다.
tobias_k

7
그러나 어색하고 명확하지 않은 구문이므로 피해야합니다.
DrMcCleod

11

무엇입니까 f = 1..__truediv__?

f값이 1 인 float의 바운드 특수 메소드입니다. 구체적으로 특별히,

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 (Abstract Syntax Tree) 구문 분석

표현식에 대해 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'>

다음 점 자체는 SyntaxError이지만 float 인스턴스에서 점으로 된 조회를 시작합니다.

>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>

아무도 이것을 언급하지 않았습니다 -이것은 이제 float에서 "바운드 메소드" 입니다 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함수 의 단점은 또 다른 파이썬 스택 프레임이 필요하다는 것인데, 바운드 메소드보다 약간 느립니다.

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