面向对象程序设计
属性
公开的数据成员可以在外部随意访问和修改,很难保证用户进行修改时提供新数据的合法性,数据很容易被破坏,也不符合类的封装性要求。解决这一问题的常用方法是定义私有数据成员,然后设计公开的成员方法来提供对私有数据成员的读取和修改操作,修改私有数据成员之前可以对值进行合法性检查,提高程序的健壮性,保证了数据完整性。
属性是一种特殊形式的成员方法,结合了公开数据成员和成员方法的优点,既可以想成员方法那样对值进行必要的检查,又可以像数据成员一样灵活地访问。
设置属性为只读,则无法修改其值,也无法为对象增加与属性同名的新成员,当然也无法删除属性。
>>> class Test:
... def __init__(self,value):
... self.__value=value #私有数据成员
... @property #修饰器,定义属性,提供对私有数据成员的访问
... def value(self): #只读属性,无法修改和删除
... return self.__value
...
>>> t = Test(3)
>>> t.value
3
>>> t.value = 5 #只读属性不允许修改值
AttributeError: can't set attribute
>>> del t.value #试图删除对象属性,失败
AttributeError: can't delete attribute
>>> t.value
3
把属性设置为可读,可修改,而不允许删除 。
>>> class Test:
... def __init__(self,value):
... self.__value=value
... def __get(self): #读取私有数据成员的值
... return self.__value
... def __set(self,v): #修改私有数据成员的值
... self.__value=v
... value=property(__get,__set) #可读可写属性,指定响应的读写方法
... def show(self):
... print(self.__value)
...
>>> t = Test(3)
>>> t.value #允许读取属性值
3
>>> t.show()
3
>>> t.value=5 #允许修改属性值
>>> t.show()
5
>>> del t.value #试图删除属性,失败
AttributeError: can't delete attribute
设置为可读,可写,可删除
>>> class Test:
... def __init__(self,value):
... self.__value=value
... def __get(self): #读取私有数据成员的值
... return self.__value
... def __set(self,v): #修改私有数据成员的值
... self.__value=v
... def __del(self): #删除对象的私有数据成员
... del self.__value
... value = property(__get,__set,__del) #可读,可写,可删除的属性
... def show(self):
... print(self.__value)
...
>>> t = Test(3)
>>> t.show()
3
>>> t.value
3
>>> t.value = 5
>>> t.value
5
>>> del t.value
>>> t.value #响应的私有数据成员已删除,访问失败
AttributeError: 'Test' object has no attribute '_Test__value'
>>> t.show()
AttributeError: 'Test' object has no attribute '_Test__value'
>>> t.value=3 #动态增加属性和对应的私有数据成员
>>> t.show()
3
类与对象的动态性、混入机制
在python中可以动态地定义类和对象增加数据成员和成员方法,这也是python动态类型的一种重要体现。
>>> import types
>>> class Car(object):
... price=1000000
... def __init__(self,c):
... self.color=c
...
>>> car1 = Car('Red')
>>> print(car1.color,Car.price)
Red 1000000
>>> Car.price=110000
>>> Car.name='QQ'
>>> car1.color='Yellow'
>>> print(car1.color,Car.price,Car.name)
Yellow 110000 QQ
>>> def setSpeed(self,s):
... self.speed=s
...
>>> car1.setSpeed=types.MethodType(setSpeed,car1)
>>> car1.setSpeed(20)
>>> print(car1.speed)
20
python类型的动态性使得我们可以动态为自定义类及其对象增加新的属性和行为,俗称混入(mixin
)机制。例如,系统中的所有用户分类非常复杂,不同用户组具有不同的行为和权限,并且可能会经常改变。
这时候可以独立地定义一些行为,然后根据需要来为不同的用户设置响应的行为能力。
>>> import types
>>> class Person(object):
... def __init__(self,name):
... assert isinstance(name,str),'name must be string'
... self.name=name
...
>>> def sing(self):
... print(self.name+'can sing.')
...
>>> def walk(self):
... print(self.name+'can walk.')
...
>>> def eat(self):
... print(self.name+'can eat.')
...
>>> zhang=Person('zhang')
>>> zhang.sing()
AttributeError: 'Person' object has no attribute 'sing'
>>> zhang.sing=types.MethodType(sing,zhang)
>>> zhang.sing()
zhang can sing.
>>> zhang.walk()
AttributeError: 'Person' object has no attribute 'walk'
>>> zhang.walk=types.MethodType(walk,zhang)
>>> zhang.walk()
zhang can walk.
>>> del zhang.walk
>>> zhang.walk()
AttributeError: 'Person' object has no attribute 'walk'