teststr = "I am a pytlon string"
# teststr[11]='h' #此代码会报错
字符串为不可变对象,任何对字符串中某个字符的修改都会抛出异常。 修改字符串中某个字符可以采用如下方式:
import array
a = array.array('u',teststr)
a[10]='h'
print(a)
array('u', 'I am a python string')
使用 tounicode()
转换为字符串。旧版本中有 tostring()
函数,但在新版本中已经被移除。
a.tounicode()
'I am a python string'
class Student(object):
def __init__(self,name,course=[] ):
self.name=name
self.course=course
def addcourse(self,coursename):
self.course.append(coursename)
def printcourse(self):
for item in self.course:
print (item)
stuA=Student ("Wang yi")
stuA.addcourse("MEnglishw")
stuA.addcourse("Math")
print(stuA.name+"'s cource:")
Wang yi's cource:
stuA.printcourse()
print( "-----------------")
MEnglishw Math -----------------
stuB=Student("MLi sann")
stuB.addcourse ("*fChineset,")
stuB.addcourse ("rPhysics")
print (stuB.name +"s course:" )
stuB.printcourse()
MLi sanns course: MEnglishw Math *fChineset, rPhysics
Li san同学所选的课多了 English和Math两门课程。这是怎么回事呢?
通过査看 id(stuA,course)
和 id(stuB,couree)
,发现这两个值是一样的,
也就是说在内存中指的是同一块地址,但 stuA
和 stuB
本身却是两个不同的对象,在实例化这两个对象的时候,
这两个对象被分配了不同的内存空间,并且调用 init()
函数进行初始化。
但由于 init()
函数的第二个参数是个默认参数,默认参数在函数被调用的时候仅仅被评估一次,
以后都会使用第一次评估的结果,因此实际上对象空间里面 course
所指向的是 list
的地址,
每次操作的实际上是 list
所指向的具体列表。这是在将变对象作为函数默认参数的时候要特别警惕的问题,
对可变对象的更改会直接影响原对象。要解决上述例子中的问题,最好的方法是传入 None
作为默认参数,
在创建对象的时候动态生成列表。具体代码如下:
def __init__(self,name,course=None):
self.name=name
if course is None :course=[]
self.course=course
对于可变对象,还有一个问题是要注意的。通过以下例子来说明:
list1=['a','b','c']
list2=list1
list1.append('d')
list1
['a', 'b', 'c', 'd']
list2
['a', 'b', 'c', 'd']
list3=list1[:]
list3.remove('a')
list3
['b', 'c', 'd']
list1
['a', 'b', 'c', 'd']
list2
['a', 'b', 'c', 'd']
id(list3)
140578622150080
id(list1)
140578622151296
id(list2)
140578622151296
上面的例子中对 listl
的切片操作实际会重新生成一个对象,因为切片操作相当于浅拷贝,
因此对 Ust3
的操作并不会改变 list1
和 list2
本身。再来看以下不可变对象的简单例子;
a=1
a+=2
print (a)
3
a的值变为3,这是理所当然的,可是仔细一想a是属于数值类型,是不可变对象,怎么会发生改变呢?
实际上Python中变量存放的是数值I在内存中的地址,数值1本身才是不可变对象。
在上面的过程中所改变的是a所指向的对象的地址,数值I并没有发生改变,
当执行 #=2
的时候重新分配了一块内存地址存放结果,并将a的引用改为该妁存地址,
而对象1所在的内存空间会最终被垃圾回收器回收。上述分析的图示如图所示。
通过 id()
函数分析也可以证实上述变化过程。
a=1
id(a)
94634129001032
id(1)
94634129001032
a+=2
a
3
id(a)
94634129001096
id(3)
94634129001096
id
函数分析也可以证实上述变化过程,对于不可变对象来说,当对其进行相关操作的时候,
Python实际上仍然保持原来的值而是重新创建一个新的对象,所以字符串对象不允许以索引的方式迸行赋值,
当有两个对象同时指向一个字符串对象的时候,对其中一个对象的操作并不会影响另一个对象。
str1="hello world"
str2=str1
str1=str1[:-5]
str1
'hello '
str2
'hello world'