我知道内联,并且从我检查过的内容不是由Python的编译器完成的。
我的问题是:是否对python的编译器进行了任何优化:
print myList.__len__()
for i in range(0, myList.__len__()):
print i + myList.__len__()
到
l = myList.__len__()
print l
for i in range(0, l):
print i + l
它是由编译器完成的吗? 如果不是:我自己这样做是否值得?
奖金问题(不那么相关):我喜欢有很多功能(更好的可读性恕我直言)...就像Python中没有内联这样可以避免(很多功能)?
答案 0 :(得分:6)
不,没有。您可以使用dis
模块将代码编译为字节码来检查Python的功能:
>>> def test():
... print myList.__len__()
... for i in range(0, myList.__len__()):
... print i + myList.__len__()
...
>>> import dis
>>> dis.dis(test)
2 0 LOAD_GLOBAL 0 (myList)
3 LOAD_ATTR 1 (__len__)
6 CALL_FUNCTION 0
9 PRINT_ITEM
10 PRINT_NEWLINE
3 11 SETUP_LOOP 44 (to 58)
14 LOAD_GLOBAL 2 (range)
17 LOAD_CONST 1 (0)
20 LOAD_GLOBAL 0 (myList)
23 LOAD_ATTR 1 (__len__)
26 CALL_FUNCTION 0
29 CALL_FUNCTION 2
32 GET_ITER
>> 33 FOR_ITER 21 (to 57)
36 STORE_FAST 0 (i)
4 39 LOAD_FAST 0 (i)
42 LOAD_GLOBAL 0 (myList)
45 LOAD_ATTR 1 (__len__)
48 CALL_FUNCTION 0
51 BINARY_ADD
52 PRINT_ITEM
53 PRINT_NEWLINE
54 JUMP_ABSOLUTE 33
>> 57 POP_BLOCK
>> 58 LOAD_CONST 0 (None)
61 RETURN_VALUE
如您所见,每次都会查找并调用__len__
属性。
Python无法知道给定方法在调用之间返回什么,__len__
方法也不例外。如果python试图通过假设来优化它,那么返回的值在调用之间是相同的,你会遇到无数不同的问题,我们甚至都没有尝试使用多线程。
请注意,使用len(myList)
会更好,而不是直接调用__len__()
挂钩:
print len(myList)
for i in xrange(len(myList):
print i + len(myList)
答案 1 :(得分:1)
不,您询问的优化不是由CPython编译器完成的。事实上,CPython编译器几乎没有做任何优化。
要亲眼看看,import dis
并使用您正在询问的代码反汇编函数:dis.dis(func)
。
未优化的原因是,下次访问属性(即使像__len__
这样的方法)完全可能是一个完全不同的对象。当然,这很少发生,但Python支持它。
属性访问确实消耗时间,因此存储对将要重复使用的属性的引用(尤其是在局部变量中)可以使代码运行得更快。但是,它降低了可读性,所以我要等到你知道给定的代码片段在应用它之前是一个瓶颈。在您的情况下,打印所花费的时间很容易超过属性访问。
归根结底,如果性能最重要的话,你首先要使用的不是Python,不是吗?