环境
TX Yun-Ubuntu 14.04.1 LTS
python-2.7.6
字符串
字符串连接
>>> "hello "+"python"
'hello python'
>>> a="hello "
>>> b="python"
>>> a+b #直接连接
'hello python'
>>> a=['p','y','t','h','o','n']
>>> str=''
>>> for i int a: #1.循环遍历
... str = str+i
...
>>> str
'python'
>>> str=''
>>> str=''.join(a) #2.join方法(高效)
>>> str
'python'
>>>
上面的例子中,对一个list a做字符串连接,用到了两种方法,第一种是直接遍历list元素,拼接到一个新的字符串中。上一节说到,python中的不可变对象,字符串也属于不可变对象。这样一来,每一次str=str+i,都创建了一个新的对象,申请多一次内存,这里仅仅只是几次拼接,如果list很大呢?
>>>import timeit
>>>from time import clock
>>>def generrate_list(num):#生成num长度的list
... i=1
... list_a=[]
... while i<num:
... list_a.append('a')
... i=i+1
... return list_a
...
>>>def use_for(list_a=[]):#遍历list连接字符串
... str=''
... for i in list_a:
... str=str+i
... return str
...
>>>def use_join(list_a=[]):#使用join连接字符串
... str=''.join(list_a)
... return str
...
>>>list10=generrate_list(10)#测试list10
>>>list100=generrate_list(100)#测试list100
>>>list1000000=generrate_list(1000000)#测试list1000000
>>>t1=timeit.Timer('use_for({})',
setup="from __main__ import use_for,list10")
>>>t2=timeit.Timer('use_join({})',
setup="from __main__ import use_join,list10")
>>>t3=timeit.Timer('use_for({})',
setup="from __main__ import use_for,list100")
>>>t4=timeit.Timer('use_join({})',
setup="from __main__ import use_join,list100")
>>>t5=timeit.Timer('use_for({})',
setup="from __main__ import use_for,list1000000")
>>>t6=timeit.Timer('use_join({})',
setup="from __main__ import use_join,list1000000")
>>>print(t1.timeit(1))#use_for,10个字符
3.0994415283203125e-06
>>>print(t2.timeit(1))#use_join,10个字符
1.00135803223e-05
>>>print(t3.timeit(1))#use_for,100个字符
4.05311584473e-06
>>>print(t4.timeit(1))#use_join,100个字符
1.19209289551e-05
>>>print(t5.timeit(1))#use_for,1000000个字符
3.0994415283203125e-06
>>>print(t6.timeit(1))#use_join,1000000个字符
1.19209289551e-05
测试过程中,我尝试更大的数据,当我生成1千万个元素的list时,系统把我进程kill了,当我生成1亿个元素的list时,出现MemoryError,好吧,再玩下去系统就要被玩坏了。
总结:循环遍历连接字符串永远慢于使用内建函数join,这鼓励我们,实现算法前先看看python是否已经内置了更好的算法。
发现:可以发现,无论数据有多大,时间都是保持在同一水平线上,和预期的耗费长时间的想法相背,这是为什么?
猜测:python的垃圾回收机制中采用引用计数的回收方式,该方法的特点就是实时性,不用的内存马上回收。
>>>i=1
>>>a="aaa"
>>>a+i
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>>a+bytes(i)#整型转字符串
a1
字符串连接整型时,需要先进行转换才可以连接
字符串截取
可以把python的字符串想象成List
>>>str="python"
>>>str[0] #索引从0开始
'p'
>>>str[-1] #表示倒数第一个
'n'
>>>str[1:4]#[头下标:尾下标]
'yth' #尾下标,不包括该下标
注意:这里截取的字符串是重新创建一个对象,并拷贝到该对象中。
引用与拷贝
既然说到对象的引用和拷贝,这里就深入研究一下
基本数据类型
>>>a=1
>>>b=a
>>>b
1
>>>a=2
>>>b
1
>>>s1="a"
>>>s2=s1
>>>s2
'a'
>>>s1="b"
>>>s2
'a'
基本数据类型是值传递,不是地址传递
列表
>>> list1=[1,2]
>>> list2=list1
>>> list2
[1, 2]
>>> list1[0]=2
>>> list1
[2, 2]
>>> list2
[2, 2]
列表是引用传递
思考:如果希望传一份拷贝,而不是引用,如果做?
>>> list2=list1[:]
>>> list2
[2, 2]
>>> list1[0]=3
>>> list1
[3, 2]
>>> list2
[2, 2]