数据封装
类型封装的步骤
1. 抽象一个类型,完成类的定义
2. 使用__slots__魔法属性,限制当前类的属性列表
3. 所有属性私有化
4. 给每个属性,提供set/get方法
备注:关于扩展属性(就是创建好对象之后增加的属性),主要是预留下来,给共享的数据使用的
如果对象中,有需要共享的数据,可以选择使用这样的属性。
面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例就拥有各自的name和score这些数据。我们可以通过函数来访问这些数据,比如打印一个学生的成绩:
>>>def print_score(std):..
.print('%s: %s'% (std.name, std.score))...
>>>print_score(bart)Bart Simpson:59
但是,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:
class Student(object):
def__init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s'% (self.name, self.score))
要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:
>>>bart.print_score()
Bart Simpson:59
这样一来,我们从外部看Student类,就只需要知道,创建实例需要给出name和score,而如何打印,都是在Student类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。
封装的另一个好处是可以给Student类增加新的方法,比如get_grade:
class Student(object)
def get_grade(self):
if self.score >=90:
return'A'
elif self.score >=60:
return'B'
else:
return'C'
同样的,get_grade方法可以直接在实例变量上调用,不需要知道内部实现细节:
>>>bart.get_grade()'C'
类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
>>> bart = Student('Bart Simpson', 59)
>>> lisa = Student('Lisa Simpson', 87)
>>> bart.age = 8
>>> bart.age
8
>>> lisa.age
Traceback (most recent call last):
File "<stdin>," line 1, in <module>
AttributeError :Student' object has no attribute 'age'
方法重载
在同一个类中,出现了两个或者两个以上同名函数/方法:方法重载
self.__nickname=nickname
@property
def username(self):
return self.__username
@username.setter
defusername(self,un):
self.__username=un
def password(self):
return self.__password
def password(self,pa):
self.__password=pa
def nickname(self):
return self.__nickname
def nickname(self,ni):
self.__nickname=ni
对象的属性
给创建的对象,添加属性
如果对象的属性,可以任意自定义的话,就会造成非常大的困扰:对象变成了变形金刚
项目往往时多个人协同开发的,开发的过程中,每个人给对象添加的属性名称和属性个数就可能不一致!
class Users:
def__init__(self,name,age):
self.__name=name
self.__age=age
def get_name(self):
return self.__name
def get_age(self):
return self.__age
#def __str__(self):
#return"姓名:%s,年龄:%s"%(self.__name,self.__age)
u=Users("汤姆",20)
print(u)
u.username="admain"
u.password="123"
u.nickname="nini"
print(u.username,u.password,u.nickname,u.get_name(),u.get_age())
运行结果
<__main__.Users object at 0x01E90670>
admain 123 nini 汤姆 20
对象属性的限制
为了避免,对象属性被滥用(创建对象后,给对象增加属性)
要给对象的属性 添加限制 限制对象只能拥有哪些属性 魔法属性__slots__
class Users:
设置当前类创建的对象 可能出现的属性列表 列表中没有出现的属性不允许使用
__slots__=["__username","__password","__nickname","__sex","__age"]
def__init__(self,username,password,nickname,sex,age):
self.__username=username
self.__password=password
self.__nickname=nickname
self.__sex=sex
self.__age=age
def__str__(self):
return"用户名:%s,密码:%s,昵称:%s,性别:%s,年龄:%s"%(\
self.__username,self.__password,self.__nickname,self.__sex,self.__age)
u=Users("123","123","marre","女","12")
u.address="驻马店"
print(u)
运行结果
u.address="驻马店"
AttributeError: 'Users' object has no attribute 'address'
把u.address="驻马店"注释掉得到的结果
用户名:123,密码:123,昵称:marre,性别:女,年龄:12
网友评论