Python 为什么时间没有';我不能处理我的代码片段吗?

Python 为什么时间没有';我不能处理我的代码片段吗?,python,ipython,timeit,Python,Ipython,Timeit,我认为这3个在逻辑上是等价的,返回集合{1,3,4}: set(sum(((1, 3), (4,), (1,)), ())) set(sum([[1, 3], [4], [1]], [])) functools.reduce(operator.or_, ({1, 3}, {4}, {1}), set()) 但是当我尝试检查ipython(python3.4.0上的v1.2.1)中每一个的性能时,timeit魔术失败了 In [1]: from operator import or_; from

我认为这3个在逻辑上是等价的,返回集合
{1,3,4}

set(sum(((1, 3), (4,), (1,)), ()))
set(sum([[1, 3], [4], [1]], []))
functools.reduce(operator.or_, ({1, 3}, {4}, {1}), set())
但是当我尝试检查ipython(python3.4.0上的v1.2.1)中每一个的性能时,timeit魔术失败了

In [1]: from operator import or_; from functools import reduce

In [2]: timeit set(sum([[1, 3], [4], [1]], []))
1000000 loops, best of 3: 604 ns per loop

In [3]: timeit set(sum(((1, 3), (4,), (1,)), ()))
1000000 loops, best of 3: 330 ns per loop

In [4]: timeit reduce(or_, ({1, 3}, {4}, {1}), set())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-83628f6293f3> in <module>()
----> 1 get_ipython().magic('timeit reduce(or_, ({1, 3}, {4}, {1}), set())')

/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py in magic(self, arg_s)
   2164         magic_name, _, magic_arg_s = arg_s.partition(' ')
   2165         magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
-> 2166         return self.run_line_magic(magic_name, magic_arg_s)
   2167 
   2168     #-------------------------------------------------------------------------

/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py in run_line_magic(self, magic_name, line)
   2085                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2086             with self.builtin_trap:
-> 2087                 result = fn(*args,**kwargs)
   2088             return result
   2089 

/usr/lib/python3/dist-packages/IPython/core/magics/execution.py in timeit(self, line, cell)

/usr/lib/python3/dist-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    190     # but it's overkill for just that one bit of state.
    191     def magic_deco(arg):
--> 192         call = lambda f, *a, **k: f(*a, **k)
    193 
    194         if isinstance(arg, collections.Callable):

/usr/lib/python3/dist-packages/IPython/core/magics/execution.py in timeit(self, line, cell)
    929             number = 1
    930             for i in range(1, 10):
--> 931                 if timer.timeit(number) >= 0.2:
    932                     break
    933                 number *= 10

/usr/lib/python3.4/timeit.py in timeit(self, number)
    176         gc.disable()
    177         try:
--> 178             timing = self.inner(it, self.timer)
    179         finally:
    180             if gcold:

<magic-timeit> in inner(_it, _timer)

TypeError: unsupported operand type(s) for |: 'set' and 'tuple'
[1]中的
:来自运算符导入或;从functools导入reduce
在[2]中:时间集(总和([[1,3],[4],[1]],[]))
1000000个循环,最好为3:604纳秒/循环
在[3]中:timeit集合(sum((1,3),(4,),(1,),())
1000000个循环,最佳3个:每个循环330纳秒
在[4]中:timeit-reduce(或u,({1,3},{4},{1}),set())
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 get_-ipython().magic('timeit-reduce(或,({1,3},{4},{1}),set())'))
/魔术中的usr/lib/python3/dist-packages/IPython/core/interactiveshell.py(self,arg_s)
2164 magic_名称,magic_arg_s=arg_s.分区(“”)
2165 magic_name=magic_name.lstrip(prefilter.ESC_magic)
->2166返回自我。运行幻术(幻术名称,幻术参数)
2167
2168     #-------------------------------------------------------------------------
/usr/lib/python3/dist packages/IPython/core/interactiveshell.py in run\u line\u magic(self,magic\u name,line)
2085 kwargs['local\u ns']=sys.\u getframe(堆栈深度).f\u locals
2086带自建存水弯:
->2087结果=fn(*args,**kwargs)
2088返回结果
2089
/timeit中的usr/lib/python3/dist-packages/IPython/core/magics/execution.py(self、line、cell)
/(f,*a,**k)中的usr/lib/python3/dist包/IPython/core/magic.py
190#但就这一点来说就太过分了。
191 def魔术装饰(arg):
-->192调用=λf,*a,**k:f(*a,**k)
193
194如果isinstance(arg,collections.Callable):
/timeit中的usr/lib/python3/dist-packages/IPython/core/magics/execution.py(self、line、cell)
929数字=1
930表示范围(1,10)内的i:
-->931如果timer.timeit(number)>=0.2:
932休息
933数字*=10
/timeit中的usr/lib/python3.4/timeit.py(self,number)
176 gc.disable()
177尝试:
-->178定时=自内(it、自定时器)
179最后:
180如果是gcold:
在内部(_it,_timer)
TypeError:|“set”和“tuple”的操作数类型不受支持

这是怎么回事?在2.7中也失败了。我不能用普通的python
timeit.timeit
方法复制这个

在我看来,这是IPython中的一个bug

首先是解决办法 避开大括号,这样通话看起来像

timeit reduce(or_, ({{1, 3}}, {{4}}, {{1}}), set())
现在问题来了 如果您看到调用堆栈,在调用级联到timeit.py之前,它会通过

/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py in run_line_magic(self, magic_name, line)
   2085                 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
   2086             with self.builtin_trap:
-> 2087                 result = fn(*args,**kwargs)
   2088             return result
现在,如果您引用这个源代码,您可以看到,在参数传递给
timeit
函数之前,它的格式是以字符串形式展开Python变量

        magic_arg_s = self.var_expand(line, stack_depth)
        # Put magic args in a list so we can call with f(*a) syntax
        args = [magic_arg_s]
self.var\u expand
调用
DollarFormatter()
作为for函数,其doc字符串沿以下行说明某些内容

class DollarFormatter(FullEvalFormatter):
    """Formatter allowing Itpl style $foo replacement, for names and attribute
    access only. Standard {foo} replacement also works, and allows full
    evaluation of its arguments. 
因此,这就是原因,集被解释为标准的{foo}替换并被转换为元组(如果是逗号分隔的值)或常量,从而使表达式

reduce(or_, ((1, 3), 4, 1), set())
这是不正确的