Python多么天真? [英] How naive is Python?

查看:37
本文介绍了Python多么天真?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

多么天真(在编译人员使用这个术语的意义上)

是当前的Python系统?例如:


def foo():

s ="这是一个测试

return(s)


s2 = foo()


字符串被复制多少次?


或者,例如:


s1 =" Test1"

s2 =" Test2"

s3 =" Test3"

s = s1 + s2 + s3


执行任何冗余副本,还是优化的情况?


怎么样这个?


kcount = 1000

s =''''

for i in range(kcount):

s + = str(i)+''''


这是O(N)还是O(N ^ 2),因为重新复制了s?


我只想了解

当前实现中异常低效的内容。谢谢。


John Nagle

解决方案



JohnHow天真(在编译人员使用这个术语的感觉是

Johncurrent Python系统?例如:


John def foo():

John s ="这是一个测试

John return( s)


John s2 = foo()


John多次复制字符串?


从不。 s和s2只是引用相同的对象(字符串是不可变的)。

执行:


def foo():

打印ID(这是一个测试)

s ="这是一个测试

打印ID(s)

返回(s)


s2 = foo()

打印ID(s2)


打印相同的值三时间。


JohnOr,例如:


John s1 =" Test1"

John s2 =" ; Test2"

John s3 =" Test3"

John s = s1 + s2 + s3


John执行多余的副本,或者是优化的情况?


未优化。你可以看到使用dis模块:


4 0 LOAD_CONST 1(''Test1'')

3 STORE_FAST 0(s1)


5 6 LOAD_CONST 2(''Test2'')

9 STORE_FAST 1(s2)


6 12 LOAD_CONST 3( ''Test3'')

15 STORE_FAST 2(s3)


7 18 LOAD_FAST 0(s1)

21 LOAD_FAST 1 (s2)

24 BINARY_ADD

25 LOAD_FAST 2(s3)

28 BINARY_ADD

29 STORE_FAST 3(s )

32 LOAD_CONST 0(无)

35 RETURN_VALUE


BINARY_ADD操作码创建一个新字符串。


JohnHow关于这个?


John kcount = 1000

John s =''''

约翰为我的范围(kcount):

John s + = str(i) +''''


John这个O(N)或O(N ^ 2)是因为重新复制了s?


O(N)。这里有一个示例:


#!/ usr / bin / env python

来自__future__进口部门的



def foo(kcount):

s =''''
$ x $ b for i in xrange(kcount):

s + = str(i)+''''


导入时间

$ x $ b for x in xrange(5,25):

t = time.time()

foo(2 ** i)

t = time.time() - t

打印2 ** i,t,t / 2 ** i


在我的笔记本电脑上,每次迭代大约翻倍并打印5e-06

t / 2 ** i在所有情况下。


Skip


在文章< hu *** *************@newssvr11.news.prodigy.net>,

John Nagle< na *** @ animats.comwrote:


多么天真(在编译人员使用这个术语的意义上)

是当前的Python系统?例如:


def foo():

s ="这是一个测试

return(s)


s2 = foo()


字符串被复制多少次?



所有这些只是移动指向相同(实习)字符串的指针。


这个怎么样?


kcount = 1000

s =''''

for i in range(kcount):

s + = str(i)+''''


这是O(N)还是O(N ^ 2),因为重新复制了s?



这是Python中二次行为的一个众所周知的(实际上是规范的)示例。标准解决方案是在列表中存储所有字符串(再次,

真的只是指向字符串的指针),然后加入所有元素:


temp = []

for i in range(1000):

temp.append(str(i))

s =""。 join(temp)


最后复制每个字符串一次(在连接操作期间),并且总体上是

O(N)。


On Mon,2007年1月15日03:25:01 +0000,John Nagle写道:


多么天真(在感觉编译人员使用这个术语)

是当前的Python系统吗?例如:


def foo():

s ="这是一个测试

return(s)


s2 = foo()


字符串被复制多少次?



让我们找出答案。以下针对Python 2.3的结果 - 其他版本可能会有所不同。


>> def foo ():



.... s ="这是一个测试

.. ..返回s

....


> > def foo2():



.... return"这是一个测试

....


>> import dis
dis.dis (foo)



2 0 LOAD_CONST 1(''这是测试'')

3 STORE_FAST 0(s)


3 6 LOAD_FAST 0(s)

9 RETURN_VALUE
10 LOAD_CONST 0(无)

13 RETURN_VALUE


>> dis.dis(foo2)



2 0 LOAD_CONST 1(''这是一个测试'')

3 RETURN_VALUE

4 LOAD_CONST 0(无)

7 RETURN_VALUE


foo和foo2函数编译为不同的字节码。 foo做了一点比boo2更多的工作,但它可能是一个微不足道的差异。


>> s1 = foo()
s2 = foo()
s1 == s2,s1是s2



(真,真)


因此字符串This is a test每次调用

函数时,都不会复制foo中的内容。但是,字符串This is a test重复了foo和foo2之间的
(两个函数不共享相同的字符串

实例):

< blockquote class =post_quotes>


>> s3 = foo2()
s3 == s1,s3是s1



(真,假)


或者,例如:


s1 =" Test1"

s2 =" Test2"

s3 =" Test3"

s = s1 + s2 + s3


执行了任何冗余副本,还是优化了?



我不相信它已经过优化。我相信在Python 2.5中简单的执行数值优化,因此x = 1 + 3表示x = 1 + 3。将编译为

x = 4,但我不认为这适用于字符串。如果你运行2.5,

你可以找到dis.dis。


这个怎么样?

kcount = 1000

s =''''

for i in range(kcount):

s + = str(i )+''''


这是O(N)还是O(N ^ 2),因为重新复制了s?



这将是O(N ** 2),除了CPython版本2.4(或它是2.5?)可以,

有时候,优化它。请注意,这是一个实现细节,并且

不适用于其他Pythons,如Jython,IronPython或PyPy。


-

Steven D''Aprano


How naive (in the sense that compiler people use the term)
is the current Python system? For example:

def foo() :
s = "This is a test"
return(s)

s2 = foo()

How many times does the string get copied?

Or, for example:

s1 = "Test1"
s2 = "Test2"
s3 = "Test3"
s = s1 + s2 + s3

Any redundant copies performed, or is that case optimized?

How about this?

kcount = 1000
s = ''''
for i in range(kcount) :
s += str(i) + '' ''

Is this O(N) or O(N^2) because of recopying of "s"?

I just want a sense of what''s unusually inefficient in the
current implementation. Thanks.

John Nagle

解决方案


JohnHow naive (in the sense that compiler people use the term) is the
Johncurrent Python system? For example:

John def foo() :
John s = "This is a test"
John return(s)

John s2 = foo()

JohnHow many times does the string get copied?

Never. s and s2 just refer to the same object (strings are immutable).
Executing this:

def foo() :
print id("This is a test")
s = "This is a test"
print id(s)
return(s)

s2 = foo()
print id(s2)

prints the same value three times.

JohnOr, for example:

John s1 = "Test1"
John s2 = "Test2"
John s3 = "Test3"
John s = s1 + s2 + s3

JohnAny redundant copies performed, or is that case optimized?

Not optimized. You can see that using the dis module:

4 0 LOAD_CONST 1 (''Test1'')
3 STORE_FAST 0 (s1)

5 6 LOAD_CONST 2 (''Test2'')
9 STORE_FAST 1 (s2)

6 12 LOAD_CONST 3 (''Test3'')
15 STORE_FAST 2 (s3)

7 18 LOAD_FAST 0 (s1)
21 LOAD_FAST 1 (s2)
24 BINARY_ADD
25 LOAD_FAST 2 (s3)
28 BINARY_ADD
29 STORE_FAST 3 (s)
32 LOAD_CONST 0 (None)
35 RETURN_VALUE

The BINARY_ADD opcode creates a new string.

JohnHow about this?

John kcount = 1000
John s = ''''
John for i in range(kcount) :
John s += str(i) + '' ''

JohnIs this O(N) or O(N^2) because of recopying of "s"?

O(N). Here''s a demonstration of that:

#!/usr/bin/env python

from __future__ import division

def foo(kcount):
s = ''''
for i in xrange(kcount) :
s += str(i) + '' ''

import time

for i in xrange(5,25):
t = time.time()
foo(2**i)
t = time.time() - t
print 2**i, t, t/2**i

On my laptop t roughly doubles for each iteration and prints around 5e-06
for t/2**i in all cases.

Skip


In article <hu****************@newssvr11.news.prodigy.net>,
John Nagle <na***@animats.comwrote:

How naive (in the sense that compiler people use the term)
is the current Python system? For example:

def foo() :
s = "This is a test"
return(s)

s2 = foo()

How many times does the string get copied?

All of those just move around pointers to the same (interned) string.

How about this?

kcount = 1000
s = ''''
for i in range(kcount) :
s += str(i) + '' ''

Is this O(N) or O(N^2) because of recopying of "s"?

This is a well-known (indeed, the canonical) example of quadratic behavior
in Python. The standard solution is to store all the strings (again,
really just pointers to the strings) in a list, then join all the elements:

temp = []
for i in range (1000):
temp.append (str(i))
s = "".join (temp)

That ends up copying each string once (during the join operation), and is
O(N) overall.


On Mon, 15 Jan 2007 03:25:01 +0000, John Nagle wrote:

How naive (in the sense that compiler people use the term)
is the current Python system? For example:

def foo() :
s = "This is a test"
return(s)

s2 = foo()

How many times does the string get copied?


Let''s find out. Results below for Python 2.3 -- other versions may vary.

>>def foo():

.... s = "This is a test"
.... return s
....

>>def foo2():

.... return "This is a test"
....

>>import dis
dis.dis(foo)

2 0 LOAD_CONST 1 (''This is a test'')
3 STORE_FAST 0 (s)

3 6 LOAD_FAST 0 (s)
9 RETURN_VALUE
10 LOAD_CONST 0 (None)
13 RETURN_VALUE

>>dis.dis(foo2)

2 0 LOAD_CONST 1 (''This is a test'')
3 RETURN_VALUE
4 LOAD_CONST 0 (None)
7 RETURN_VALUE

foo and foo2 functions compile to different byte-code. foo does a little
more work than foo2, but it is likely to be a trivial difference.

>>s1 = foo()
s2 = foo()
s1 == s2, s1 is s2

(True, True)

So the string "This is a test" within foo is not copied each time the
function is called. However, the string "This is a test" is duplicated
between foo and foo2 (the two functions don''t share the same string
instance):

>>s3 = foo2()
s3 == s1, s3 is s1

(True, False)

Or, for example:

s1 = "Test1"
s2 = "Test2"
s3 = "Test3"
s = s1 + s2 + s3

Any redundant copies performed, or is that case optimized?

I don''t believe it is optimized. I believe that in Python 2.5 simple
numeric optimizations are performed, so that "x = 1 + 3" would compile to
"x = 4", but I don''t think that holds for strings. If you are running 2.5,
you could find out with dis.dis.

How about this?

kcount = 1000
s = ''''
for i in range(kcount) :
s += str(i) + '' ''

Is this O(N) or O(N^2) because of recopying of "s"?

That will be O(N**2), except that CPython version 2.4 (or is it 2.5?) can,
sometimes, optimize it. Note that this is an implementation detail, and
doesn''t hold for other Pythons like Jython, IronPython or PyPy.

--
Steven D''Aprano


这篇关于Python多么天真?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆