类的封装

概念

面向对象语言的三大特征:封装, 继承, 多态 (鸭子模型)
python中不存在真正的多态
广义的封装: 类和函数定义本身就是封装的体现

狭义的封装:一个类的某些属性,不希望外界直接访问,而是把这个属性私有化[只有当前类持有],然后暴露给外界一个访问的方法即可.

封装的本质:就是属性私有化的过程

封装的好处:提供了数据的复用性,保证了数据的安全性

举例:插排

在class内部可以有属性和方法,而外部的代码可以通过直接调用实例变量的方法来操作数据,这样就隐藏了内部的复杂逻辑。

但是从我们之前定义的class来看,外部代码还是可以自由的修改一个实例的name等属性。

使用

如果要让内部的属性不被外部访问,可以把属性名前加两个下划线,在python中以双下划线开头的变量就变成了一个私有的变量,只有内部可以访问,而外部不能访问。

class Person(object):
    def __init__(self, name, age, height, money):
        self.name = name
        self.__age__=age
        self.__money = money

修改完毕之后,对于外部的代码几乎没有变动,但是已经无法从外部访问money变量了

>>>per = Person("hanmeimei", 20, 170, 10000)
>>>per.__money
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__money'

这样就确保了外部的代码不能随意的修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。

但是,如果外部的代码需要获取money的属性的时候该怎么办呢?

我们可以通过getMoney与setMoney的方法来操作数据

class Person(object):
    def run(self):
        print(self.__money)
    def eat(self):
        print("eat",food)
    def __init__(self, name, age, height, weight, money):
        self.name = name
        self.__age__=age
        self.weight = weight
        self.__money = money
        
    #通过内部方法,去修改私有属性
    #通过自定义的方法实现对私有属性的赋值与取值
    #set方法:setxxx
    def setMoney(self, money):
        #数据的过滤
        if money < 0:
            money = 0
        self.__money = money
     
    #get方法:getXXX
    def getMoney(self):
        return self.__money

per = Person("hanmeimei", 20, 170, 55, 10000)

#1.属性被私有化之后的访问
#如果要让内部属性不被外部直接访问,在属性前加两个下划线(__),
#在python中如果在属性前面加两个下划线,name这个属性就变成了私有属性[private]
#私有属性的含义:在外界不能像以前那么直接访问
#print(per.__money) #无法在外界直接访问
per.run() #内部可以访问

#2.解决办法: 如何对私有属性取值和赋值
#但是,需要注意的是,在python找那个私有不是绝对的
#属性被私有化之后,可以通过get/set的方法进行访问
per.setMoney(10)
print(per.getMoney())



#4.特殊情况
#在Python中 __xxx__ 属于特殊变量,将不再属于私有变量,可以直接访问
print(per.__age__)

#在python中 _xxx变量,这样的实例变量外部是可以访问的,但是,按照约定的规则
#当我们看到这样的变量时,意思虽然是"虽然我可以被访问,但是请把我视为私有变量,不要直接访问我"
print(per._height)

双下划线开头的变量是不是一定不能够从外部访问呢?其实也不是。

# 不能直接访问per.__money是因为python解释器把__money变成了_Person__money
# 仍然可以使用_Person__money去访问,但是强烈不建议这么干,不同的解释器可能存在解释的变量名不一致
per = Person("hanmeimei", 20, 170, 55, 10000)
per._Person__money = 1
print(per.getMoney())

总的来说,python本身没有任何机制能够阻止你干坏事,一切靠自觉

注意:这种错误的写法

per = Person("hanmeimei", 20, 170, 55, 10000)
per.__money = 1
print(per.__money)
# 从表面上看,外部代码“成功的设置了__money”变量,
# 但是实际上这个__money变量和内部的__money变量不是同一个变量,而是外部的代码给per新增了一个变量
# 测试一下
print(per.getMoney())
单下划线,双下划线,头尾下划线的说明
'''
头尾下划线__foo__():定义特殊的方法,一般是系统定义名字,类似于__init__()

单下划线:_foo:以单下划线开头的表示是protected类型的变量,即保护类型的变量只允许本身与子类访问,
不能用于from module import *

双下划线:__foo:双下划线的表示的是私有类型(private)的变量,只能允许这个类的本身进行访问。
'''

练习

'''
需求:富二代开着骚红色玛莎拉蒂,很自豪的跟朋友炫耀...

分析:
汽车类:
特征:品牌,颜色
行为:在马路上奔驰

富二代类:
特征:姓名
行为:开车,炫耀
'''
form car import Car
from richman import RichMan

#1.创建富二代对象
man = RichMan("王思聪")

#2.创建汽车对象
car = Car("玛莎拉蒂","骚红色")

#富二代的行为
man.dirveCar(car)
man.showCar(car)

class Car(object):
    #构造函数
    def __init__(self,brand, color):
        self.__brand = brand
        self.__color = color
    
    #get/set函数
    def setBrand(self, brand):
        self.__brand = brand
    
    def getBrand(self,brand):
        return self.__brand
    
    def setColor(self, color):
        self.__color = color
        
     def getColor(self):
        return self.__color
   	
     #成员函数
      def run(self):
        print("%s在马路上奔驰"%self.__brand)
        

class  RichMan(object):
    #构造函数
    def __init__(self, name):
        self.__name = name
        
    #get/set函数
    def setName(self, name):
        self.__name = name
     
    def getName(self):
        return  self.__name
    
    #成员函数
    def driverCar(self,car)
    	print("福二代%s开着他新车%s"%(self.__name, self.getBrand()))
     def showCar(self,car)
    	print("很自豪的炫耀起来,你看这辆%s,你看这%s成色...."%(car.getBrand(), car.getColor()))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值