Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么是'1..\u truediv'?Python是否有一个。。(“dot-dot”)符号语法?_Python_Python 3.x_Syntax_Operators_Python 2.x - Fatal编程技术网

什么是'1..\u truediv'?Python是否有一个。。(“dot-dot”)符号语法?

什么是'1..\u truediv'?Python是否有一个。。(“dot-dot”)符号语法?,python,python-3.x,syntax,operators,python-2.x,Python,Python 3.x,Syntax,Operators,Python 2.x,最近,我遇到了一种以前在学习python时以及在大多数教程中从未见过的语法,。表示法,它看起来像这样: f = 1..__truediv__ # or 1..__div__ for python 2 print(f(8)) # prints 0.125 我认为它与(当然,除了更长之外)完全一样: 但我的问题是: 它怎么能做到呢 这两个点到底意味着什么 如何在更复杂的语句中使用它(如果可能) 这可能会在将来为我节省许多代码行…:)您拥有的是一个不带尾随零的浮点文本,然后您可以访问的\uu

最近,我遇到了一种以前在学习python时以及在大多数教程中从未见过的语法,
表示法,它看起来像这样:

f = 1..__truediv__ # or 1..__div__ for python 2

print(f(8)) # prints 0.125 
我认为它与(当然,除了更长之外)完全一样:

但我的问题是:

  • 它怎么能做到呢
  • 这两个点到底意味着什么
  • 如何在更复杂的语句中使用它(如果可能)

这可能会在将来为我节省许多代码行…:)

您拥有的是一个不带尾随零的
浮点
文本,然后您可以访问的
\uuu truediv\uu
方法。它本身不是一个操作员;第一个点是浮点值的一部分,第二个点是访问对象属性和方法的点运算符

您可以通过执行以下操作达到相同的目的

>>> f = 1.
>>> f
1.0
>>> f.__floordiv__
<method-wrapper '__floordiv__' of float object at 0x7f9fb4dc1a20>

在这里,我们将1.0添加到2.0,这显然会产生3.0。

两个点加在一起一开始可能有点尴尬:

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

这个问题已经得到了充分的回答(即s的答案),但也可以验证这些答案的正确性

让我回顾一下现有的答案:
不是一个单一的语法元素

您可以检查源代码的使用情况。这些标记表示代码的解释方式:

>>> 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”操作符),而
\uuu truediv\uuu
是方法名。因此,这只是访问float
1.0
\uuuu truediv\uuu
方法

查看生成的字节码的另一种方法是使用它。这实际上显示了执行某些代码时执行的指令:

>>> 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
这基本上是一样的。它加载常量
1.0
的属性
\uuuu truediv\uuuu


关于你的问题

如何在更复杂的语句中使用它(如果可能的话)

即使您可能永远都不应该编写这样的代码,因为不清楚代码在做什么。所以请不要在更复杂的语句中使用它。我甚至认为你不应该在如此“简单”的语句中使用它,至少你应该用括号来分隔指令:

f = (1.).__truediv__
这肯定更具可读性,但大致如下:

from functools import partial
from operator import truediv
f = partial(truediv, 1.0)
那就更好了

使用
partial
的方法也保留了(
1..\uuuuu truediv\uuuuu
方法不保留!),这可以通过以下小片段演示:

>>> 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)
不是通过
浮点运算来计算的。
而是通过
复杂运算来计算的。
-
运算符。当正常操作返回
未实现
时,truediv
确保调用反向操作,但直接对
\u truediv
进行操作时,不会出现这些回退。这种“预期行为”的缺失是你(通常)不应该直接使用魔法方法的主要原因

什么是
f=1..\uuu truediv\uuu
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)
以及:

如果我们这样做:

f = one.__truediv__
我们保留一个绑定到该绑定方法的名称

>>> f(2)
__truediv__ called
0.5
>>> f(3)
__truediv__ called
0.3333333333333333
如果我们在一个紧密的循环中进行点查找,这可以节省一点时间

解析抽象语法树(AST) 我们可以看到,解析表达式的AST告诉我们,我们正在获得浮点数
1.0
上的
\uu truediv\uuu
属性:

>>> import ast
>>> ast.dump(ast.parse('1..__truediv__').body[0])
"Expr(value=Attribute(value=Num(n=1.0), attr='__truediv__', ctx=Load()))"
>>> f = 1..__truediv__
>>> f
<method-wrapper '__truediv__' of float object at 0x127F3CD8>
>>> f(2)
0.5
>>> f(3)
0.33333333333333331
您可以通过以下方式获得相同的结果函数:

f = float(1).__truediv__

演绎 我们也可以通过扣除的方式到达那里

让我们把它建起来

1本身就是一个
int

>>> 1
1
>>> type(1)
<type 'int'>
我们可以更容易地完成相同的功能:

>>> def divide_one_by(x):
...     return 1.0/x
...     
>>> divide_one_by(2)
0.5
>>> divide_one_by(3)
0.33333333333333331
演出
divide\u one\u 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]

所以我们发现的是一个为了简洁而牺牲了很多清晰度的开发人员。也许有人正在把他的源代码保存到5.5英寸软盘上?@ThomasAyoub应该是5.25英寸iirc;-)@有趣的事实是,你也可以在JavaScript中这样做:
1..toString()
注意:
(1)。\uuu truediv\uuu
1..\uu truediv\uu
并不完全相同,前者调用
int.\uu truediv\uu
,而后者调用
float.\uu truediv\uu
。或者,您也可以使用
1.\uuu truediv\uuu
(带空格)`注意
1//8
在任一版本的Python中都是
0
,而不是
0.125
。这让我想起了
if(x就是一个使用中的例子。@KeithC高质量的答案和注释表明示例代码需要洞察才能理解,对许多人来说是令人惊讶的,它有更清晰、更全面、至少同样有效的替代方案。我的主要抱怨是可读性很重要。把聪明放在最需要的地方——与人交流。这是令人惊讶的是,为什么这些语法是有效的,但是
1.\uuu truediv\uuuu
不是?@AlexHall-See.
似乎被解析为数字的一部分,然后方法访问器的
就丢失了。但是,因为它的语法笨拙且不清楚,所以应该避免它。
>>> 1.
1.0
>>> type(1.)
<type 'float'>
>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>
>>> 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
>>> 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]