封装

封装

1 什么是封装

  封装就是将复杂的丑陋的隐私的细节隐藏到内部 对外提供简单的使用接口 对外隐藏内部实现细节 并提供访问的接口

2 为什么需要封装

两个目的

  1 为了保证 关键数据的安全性

  2 对外部隐藏实现细节 隔离复杂度

  3 什么时候应该封装

当有一些数据不希望外界可以直接修改时 当有一些函数不希望给外界使用时

4 如何使用

语法

在初始化的时候self.后面加__      会隐藏属性

class Person:
    def __init__(self,id_number,name,age):
        self.__id_number = id_number
        self.name = name
        self.age = age


p = Person('1111111111','jack',40)

5 被封装的内容的特点

  1 内容不能直接访问

  2 内部依然可以使用

class Person:
    def __init__(self,id_number,name,age):
        self.__id_number = id_number
        self.name = name
        self.age = age
    # def show_id(self):
    #     print(self.__id_number)

p = Person('1111111111','jack',40)
p.__id_number = '222'
print(p.__id_number)

p.show_id()

如何访问被封装的函数

学习了封装后就可以控制舒属性的权限

在python 中只要两种权限

  1 公开的 么人就是公开的

   2 私有的 只能有当前类自己的使用

在外界访问私有的内容

  属性虽然被封装 但是还是需要使用的 在外界如何访问 通过定义方法来完成对私有属性的修改和访问

# 这是一个下载器类   需要提供一个缓存大小这样的属性
# 缓存大小不能超过内存限制
class Downloader:
    def __init__(self,filename,url,buffer_size):
        self.filename = filename
        self.url = url
        self.__buffer_size = buffer_size

    def start_download(self):
        if self.__buffer_size <= 1024*1024:
            print('开始下载.....')
            print('当前缓冲器大小',self.__buffer_size)
        else:
            print('内存炸了')

    def set_buffer_size(self,size):
        # 可以在方法中添加额外的逻辑
        if not type(size) == int:
            print('SB   缓冲器必须是整型')
        else:
            print('修改成功')
        self.__buffer_size = size

    def get_buffer_size(self):
        return self.__buffer_size
d = Downloader('互撸娃','http://www.baidu.com',1024*1024)

# 通过函数去修改内部封装的属性
d.set_buffer_size(1024*512)


# 通过函数访问内部封装的属性
print(d.get_buffer_size())
print(d.filename)

d.start_download()

这样一来我们可以在外界修改这个关键数据是 做一些限制

property装饰器

通过方法来修改或访问属性,本身没什么问题 但是这给对象的使用者带来了麻烦 使用必须知道那些是普通属性 那些是私有属性 需要使用不同的方式来调用他们 property 装饰就是为了使得调用方式一致

有三个相关的装饰器

1 property   改装器 用在获取属性的方法上
2 @key.setter   改装器 用在修改属性的方法上
3 @key.deleter   改装器 用在删除属性的方法上

注意    key是被property装饰的方法的名称  也就是属性的名称
内部会创建一个对象 变量名称就是函数名称
所以在使用setter和deleter时必须使用对象的名称  去调用方法      既对象.setter     这三个需要哪个写那个
class A:
    def __init__(self,name,key):
        self.__name = name
        self.__key = key

    @property
    def key(self):
        return self.__key

    @key.setter
    def key(self,new_key):
        if new_key <= 100:
            self.__key = new_key
        else:
            print("key 必须小于等于100")

    @key.deleter
    def key(self):
        print("不允许删除该属性")
        del self.__key

    # @property
    # def name(self):
    #     return self.__name
    #
    # @name.setter
    # def name(self,new_name):
    #     self.__name = new_name

a = A("jack",123)
# print(a.name)
# # print(a.get_key())
#
print(a.key)
a.key = 321
print(a.key)
del a.key
print(a.key)

a.name = "xx"
print(a.name)
View Code

python实现封装的原理

就是在加载类的时候 把__替换成了_类名__

python一般不会强制要求程序必须怎么怎么的

class A:
    def __init__(self,key):
        self.__key = key

    @property
    def key(self):
        return self.__key

    @key.deleter
    def key(self):
        del self.__key


a = A("123")
# print(a.key)
# print(a.__dict__)

print(a._A__key)

a.__name = 1

print(a.__dict__)


# print("__key".replace("__","_A__"))

property装饰器可以用来实现计算属性

计算属性指的是:属性的值不能直接获得 必须通过计算才能获取

例如: 正方形的面积

class Square:
    def __init__(self,long):
        self.long = long
        # 面积
        # self.area = self.long * self.long

    @property
    def area(self):
        return self.long * self.long

s = Square(10)
print(s.area)

s.long = 20
print(s.area)

s.long = 50
print(s.area)

练习: 定义一个类叫做person
包含三个属性 身高 体重 BMI
BMI的值需要通过计算得来 公式 体重 / 身高的平方

class My_BMI:
    def __init__(self,height,weight):
        self.height = height
        self.weight = weight
    @property
    def BMI(self):
        return (self.weight  / (self.height * self.height))
print('输入数字!!!阿拉伯数字!!!谢谢')
height_m = input('请输入你的身高:单位为cm>>>:')
if height_m.isdigit():
    height_cm = int(height_m) / 100
    weight = input('请输入您的体重:单位为kg>>>:')
    mybmi = My_BMI(float(height_cm),float(weight))
    print(round(mybmi.BMI,1))
else:
    res = round(float(height_m))
    height_cm = res / 100
    weight = input('请输入您的体重:单位为kg>>>:')
    mybmi = My_BMI(float(height_cm), float(weight))
    print(round(mybmi.BMI, 1))
BMI计算

接口 (了解)

接口是一组功能的集合 但是接口中仅包含功能的名字 不包含具体的实现代码

接口本质是一套协议标准 遵循这个标准的对象就能被调用 接口的目的就是为了提高扩展性 :

例如电脑提前制定一套usb接口协议,只要你遵循该协议 你的设备就可以被电脑使用 不需要关心到底是鼠标还是键盘

class USB:
    def open(self):
        pass

    def close(self):
        pass

    def read(self):
        pass

    def write(self):
        pass

class Mouse(USB):
    def open(self):
        print('鼠标能用了...')

    def close(self):
        print('鼠标不能用了....')

    def read(self):
        print('获取光标位置.....')

    def write(self):
        print('鼠标不支持写......')

def pc(usb_device):
    usb_device.open()
    usb_device.read()
    usb_device.write()
    usb_device.close()

m = Mouse()
# 将鼠标传给电脑
pc(m)

class Key_board(USB):
    def open(self):
        print('键盘能用了...')

    def close(self):
        print('键盘不能用了....')

    def read(self):
        print('获取键盘的按键字符.....')

    def write(self):
        print('可以写入灯光颜色......')

# 来了一个键盘对象
k = Key_board()

pc(k)
View Code

在上述案例中 pc的代码 一旦完成 后期 无论什么样的设备 只要遵循USB接口协议 都能被电脑所调用 接口主要是方便了对象的使用者 降低使用者的学习难度 只要学习一套使用方法 就可以以不变应万变

问题 如果子类没有按照你的协议来设计,也没办法限制他,将导致代码无法运行

抽象类 (了解)

指的是包含抽象方法的类 没有函数体的类 作用 可有限制子类必须实现类中定义的抽象方法

finally python 一般不会限制你必须怎么写 作为一个优秀的程序员 就应该自觉遵守相关协议

所以有了鸭子类型一个说法 如果这个对象长得像鸭子 走路像鸭子 那他就是鸭子

你只要保证按照你的类相关的协议写代码 也可以大刀提高扩展性的目的

class Mouse:
    def open(self):
        print("鼠标开机.....")

    def close(self):
        print("鼠标关机了...")

    def read(self):
        print("获取了光标位置....")

    def write(self):
        print("鼠标不支持写入....")



def pc(usb_device):
    usb_device.open()
    usb_device.read()
    usb_device.write()
    usb_device.close()

m = Mouse()
# 将鼠标传给电脑
pc(m)

class KeyBoard:
    def open(self):
        print("键盘开机.....")

    def close(self):
        print("键盘关机了...")
        
    def read(self):
        print("获取了按键字符....")
        
    def write(self):
        print("可以写入灯光颜色....")

        
# 来了一个键盘对象
k = KeyBoard()
pc(k)

class UDisk:
    def open(self):
        print("U盘启动了...")

    def close(self):
        print("U盘关闭了...")

    def read(self):
        print("读出数据")

    def write(self):
        print("写入数据")

u = UDisk()
pc(u)
View Code
原文地址:https://www.cnblogs.com/xuzhaolong/p/11251570.html