CPython tokenize workflow:
- https://github.com/python/cpython/blob/master/Lib/tokenize.py#L535
- NUMBER — https://github.com/python/cpython/blob/master/Lib/tokenize.py#L80
- Imagnumber — https://github.com/python/cpython/blob/master/Lib/tokenize.py#L79
- Floatnumber — https://github.com/python/cpython/blob/master/Lib/tokenize.py#L78
- Intnumber — https://github.com/python/cpython/blob/master/Lib/tokenize.py#L73
We can manually parse the statement to tokens and see how cpython works here
$ echo "1.__str__()" | python3 tokenize.py
1,0-1,2: NUMBER '1.'
1,2-1,9: NAME '__str__'
1,9-1,10: OP '('
1,10-1,11: OP ')'
1,11-1,12: NEWLINE '\n'
2,0-2,0: ENDMARKER ''
we can see here, it takes ‘1.’ to a number, and means Floatnumber is in a higher priority than Intnumber.
So we have two ways to make it work:
>>> (1).__str__()
'1'
$ echo "(1).__str__()" | python3 tokenize.py
1,0-1,1: OP '('
1,1-1,2: NUMBER '1'
1,2-1,3: OP ')'
1,3-1,4: OP '.'
1,4-1,11: NAME '__str__'
1,11-1,12: OP '('
1,12-1,13: OP ')'
1,13-1,14: NEWLINE '\n'
2,0-2,0: ENDMARKER ''>>> 1..__str__()
'1.0'
$ echo "1..__str__()" | python3 tokenize.py
1,0-1,2: NUMBER '1.'
1,2-1,3: OP '.'
1,3-1,10: NAME '__str__'
1,10-1,11: OP '('
1,11-1,12: OP ')'
1,12-1,13: NEWLINE '\n'
2,0-2,0: ENDMARKER ''
But looks like the second one is not the expected one.
Anyway, that’s all.