一、类的封装:
1.概念:
广义的封装:函数和类的定义本身,就是封装的体现
狭义的封装:一个类的某些属性,在使用的过程 中,不希望被外界直接访问,而是把这个属性给作为私有的【只有当前类持有】,然后暴露给外界一个访问的方法即可【间接访问属性】
封装的本质:就是属性私有化的过程
封装的好处:提高了数据的安全性,提高了数据的复用性
2.属性、方法的私有化:
如果想让成员变量不被外界直接访问,则可以在属性名称的前面添加两个下划线__,成员变量则被称为私有成员变量
私有属性的特点:只能在类的内部直接被访问,在外界不能直接访问
# 类
class Person:
def __init__(self, name, age, sex):
self.name = name # 公有属性
self.__age = age # 私有属性: 双下划线开头的属性, 只能在当前类内部使用
self._sex = sex # 公有属性,但是不建议这么写
def run(self):
print(self.__age)
self.__eat()
# 私有方法
def __eat(self):
print("eat")
# 对象
p = Person('鹿晗', 30, '男')
print(p.name)
# print(p.__age) # 报错,__age是私有属性
print(p._sex)
p.run()
print()
# p.__eat() # 报错,__eat()是私有方法
类中出现 ‘__属性名/__方法名’时说明属性/方法是私有属性/方法,子类无法继承且外部无法调用。
在上述程序中私有类__sex与私有方法__eat()都是无法调用的,但是可以通过其他手段进行调用,但是不介意这样使用。
下面的方式可以调用私有属性或私有方法,但是不要这么用
print(p._Person__age)
p._Person__eat()
3.get函数和set函数
get函数和set函数并不是系统的函数,而是自定义的,为了和封装的概念相吻合,起名为getXxx和setXxx
get函数:获取值
set函数:赋值【传值】
因为类的私有属性/方法是无法被继承与调用的,因此我们引入get函数与set函数来对私有属性/方法进行获取与修改。
class Person2():
def __init__(self,name,age):
self.name = name
self.__age = age
#特殊情况一
self.__weight__ = 20.0
#特殊情况二
self._height = 155.0
def myPrint(self):
print(self.name,self.__age)
p2 = Person2("abc",10)
p2.myPrint() #abc 10
3.1 get函数:
#get函数:获取成员变量的值
#命名方式:getXxx
#特点:需要设置返回值,将成员变量的值返回
def getAge(self):
return self.__age
print(p2.getAge()) # 10
3.2 set函数:
#set函数:给成员变量赋值
#命名方式:setXxx
#特点:需要设置参数,参数和私有成员变量有关
def setAge(self,age):
#数据的过滤
if age < 0:
age = 0
self.__age = age
p2.setAge(22)
print(p2.getAge()) # 22
总结:通过将属性私有化之后,然后提供get函数和set函数,外部代码就不能随意更改成员变量的值,这样在一定程度上保证了数据的安全性
4.@property装饰器
装饰器的作用:可以给函数动态添加功能,对于类的成员方法,装饰器一样起作用
Python内置的@property装饰器的作用:将一个函数变成属性使用
@property装饰器:简化get函数和set函数
使用:@property装饰器作用相当于get函数,同时,会生成一个新的装饰器@属性名.settter,相当于set函数的作用
作用:使用在类中的成员函数中,可以简化代码,同时可以保证对参数做校验
class Person1():
def __init__(self,name,age):
self.__name = name
self.__age = age
def myPrint(self):
print(self.__name,self.__age)
@property
def age(self):
return self.__age
#注意:函数的命名方式:需要和@property中函数的命名保持一致
#作用:相当于set函数,设置参数,给成员变量赋值
@age.setter
def age(self,age):
if age < 0:
age = 0
self.__age = age
@property
def name(self):
return self.__name
@name.setter
def name(self,name):
self.__name = name
p1 = Person1("abc",10)
p1.myPrint() #abc 10
#p1.setAge(20)
#print(p1.getAge())
print(p1.age) #10
p1.age = 18 #相当于调用了set函数,将18传值,实质调用的是@age.setter修饰的函数
print(p1.age) #相当于调用了get函数,将成员变量的值获取出来,实质调用的是@peoperty修饰的函数
p1.name = "zhangsan"
print(p1.name)
5.私有方法
如果类中的一个函数名前面添加__,则认为这个成员函数时私有化的
特点:也不能在外界直接调用,只能在类的内类调用
class Site():
def __init__(self,name):
self.name = name
def who(self):
print(self.name)
self.__foo