Python中一切皆对象,每一个对象都有一个唯一的标示符( id()
)、类型( type()
)以及值。
对象根据其值能否修改分为可变对象和不可变对象,其中数字、字符串、元组属于不可变对象,
字典以及列表、宇节数组属于可变对象3而“菜鸟”常常会试图修改字符串中某个字符。 看下面这个例子:
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:")
stuA.printcourse()
print( "-----------------")
stuB=Student("MLi sann")
stuB.addcourse ("*fChineset,")
stuB.addcourse ("rPhysics")
print (stuB.name +"s course:" )
stuB.printcourse()
Wang yi's cource: MEnglishw Math ----------------- MLi sanns course: MEnglishw Math *fChineset, rPhysics
Li san同学所选的多了 English和Math两N课程。这是怎么回事呢?
通过査看 id(stuA,course)
和 id(stuB,couree)
,发现这两个值是一样的,
也就是说在内存中指的是同一块地址,但 stuA
和 stuB
本身却是两个不同的对象e在实例化这两个对象的时候,
这两个对象被分配了不同的内存空间,并且调用 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)
140560188742528
id(list1)
140560188455104
id(list2)
140560188455104
上面的例子中对 listl
的切片操作实际会重新生成一个对象,因为切片操作相当于浅拷贝,
因此对 Ust3
的操作并不会改变 list1
和 list2
本身。再来看以下不可变对象的简单例子;
a=1
a+=2
print (a)
3
a的值变为3,这是理所当然的,可是仔细一想a是属于数值类型,是不可变对象.怎么会发生改变呢?
实际上Python中变fta存放 的是数值I在内存中的地址,数值1本身才是不可变对象。
在上面的过程中所改变的是a所指向的对象的地址,数值I并没有发生改变,
当执行 #=2
的时候重新分配了一块内存地址存放结果,并将a的引用改为该妁存地址,
而对象1所在的内存 空间会最终被垃圾回收器回收。上述分析的图示如图所示。
通过 id()
函数分析也可以证实上述变化过程3
a=1
id(a)
94230931139144
id(1)
94230931139144
a+=2
a
3
id(a)
94230931139208
id(3)
94230931139208
id函数分析也可以证实上述变化过程,对于不可变对象来说,当对其进行相关操作的时候, Python实际上仍然保持原来的值而是重新创建一个新的对象,所以字符串对象不允许以索引的方式迸行赋值, 当有两个对象同时指向一个字符串对象的时候.对其中一个对 象的操作并不会影响另一个对象。
str1="hello world"
str2=str1
str1=str1[:-5]
str1
'hello '
str2
'hello world'