封装

一、什么是封装?

  封装就是指隐藏对象的属性和实现的细节,仅对外公开提供简单的接口。

控制程序中属性的访问权限:Python中权限分为两种:

  1:公开 外界可以直接访问和修改

  2:私有 外界不能直接访问和修改,在当前类中可以直接修改和访问

二、为什么要封装,有什么好处?

  1、为了保护数据的安全 (身份证信息,银行卡密码等)

  2、对外隐藏实现的细节,为了隔离复杂度  (电脑的开机功能,手机的使用不需要考虑如何实现等)

三、什么时候应该使用封装:

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

四、封装的语法:

  在属性名前添加两个下划线__ 将其设置为私有的

语法和应用场景: 外界不能直接访问,内部依然可以使用

class Person:
    def __init__(self,name,age,id_number):
        self.__id_number=id_number # 封装起来 变为私有
        self.age=age
        self.name=name

p = Person("5272219544082421124","Gavin",20)
p.id_number="15464487648"
print(p.id_number)  
print(Person.__dict__)

>>>

15464487648    

{'__module__': '__main__', '__init__': <function Person.__init__ at 0x000001D3B65D57B8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}

 

五、在外界访问私有的内容

  属性虽然被封装了,但是还是需要使用的,在外界如何访问?

可以通过 定义类完成对私有属性对的修改和访问

"""
这是一个下载器类,需要提供一个缓存大小这样的属性
缓存大小不能超过内存的极限

"""

class Downloader: # 定义一个类

    def __init__(self,filename,url,buffer_size): #定义属性
        self.filename=filename
        self.url=url
        self.__buffer_size=buffer_size  # 初始化封装数据
    def  start_downloader(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("对不起,缓存的数据必须是整型的")
        else:
            print("缓存区的大小修改成功!")

            self.__buffer_size=size
    def get_buffer_size(self):  # 获取缓存的数据大小
        return self.__buffer_size

d=Downloader("我是谁,没有绝对安全的系统","https//www.baidu.com",1024*1024)
d.set_buffer_size(1024*60)  # 修改下载缓存的大小

print(d.get_buffer_size())

d.start_downloader()  # 通过修改类之后可以访问是私有的数据

# 修改后都可以获取数据
d.set_buffer_size(1024*6)
d.get_buffer_size()
d.start_downloader()

六、封装之property

1、什么是:property ?

  property是一个装饰器,将一个方法伪装成普通的属性,其特殊之处在在于,该方法会在修改属性值时自动执行

2、为什么要用property?  

  通过方法来修改或访问属性,本身没什么问题,但是这给对象的使用者带来了麻烦,

使用必须知道哪些是普通属性,哪些是私有的属性,需要使用不同的方式来调用他们;

property装饰器就是为了使得他们的调用方式统一(用统一的调用方式)

有三个相关的装饰器:

  1、property     该装器用在获取属性的方法上
  2、@key.setter   该装器会在修改属性值时自动执行
  3、@key.deleter  该装器会在删除属性值自动执行

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
        print(self.key)

a=A("James",986059)
print(a.key)
a.key=123
print(a.key)

  注意  :key是被property装饰的方法的名称  也就是属性的名称

      内部会创建一个对象 变量名称就是函数名称,所以在使用setter和deleter时,必须保证使用的名称取调用方法

    所以是key.stter

七、property可以用来实现属性的计算:

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

例如:正方形求面积:

class Square:
    def __init__(self,width):
        self.width=width
    @property # 让属性装换为普通类 
    def area(self):
        return self.width*self.width
    
s=Square(10)
print(s.area)

s.width=20
print(s.area)

s.width=2
print(s.area) 

>>
E:\PY\venv\Scripts\python.exe E:/PY/封装.py

100
400
4

八、Python实现封装的原理

  就是在加载类的时候把__替换成了_类名_,Python一般不会强制要求程序员必须怎么怎么的,所以一般默认不更改

类在加载时默认把__给更改了,而且只改一次

九、接口 (了解)

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

接口的本质是一套协议标准,遵循这个标准的对象就能被调用

  接口的目的就就是为了提高扩展性:

例如:电脑提前指定一套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 KeyBoard(USB):
    def open(self):
        print("键盘开机.....")

    def close(self):
        print("键盘关机了...")

    def read(self):
        print("获取了按键字符....")

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

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

    接口主要是方便了对象的使用者,降低使用者的学习难度,只要学习了一套使用方法,就可以以不变应万变

十、抽象类(了解):

  import abc

  abstract class
翻译为抽象类
抽象类的定义 :
类中包含 没有函数体的方法

  指的是包含抽象方法(没有函数的方法)的类

class person:
    def run(self):
        pass

# 函数体中没有方法 这种就叫抽象类

作用:可以实现强制性要求子类必须实现父类声明的方法

抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化,且有存在没有实现的方法;

import abc

class AClass(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def run(self):
        pass
    @abc.abstractmethod
    def run1(self):
        pass


class B(AClass):

    def run(self):
        print("runrunrurn...")

b = B()

十一、鸭子类型(了解)

  Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

python比较随意不会限制程序员如何去编写程序,但作为合格的程序员就必须自觉遵守相关协议(接口)

就是要保证你的类按照相关的协议类编写,也可以达到提高扩展性的目的

小结:

接口是一套协议规范,明确子类们应该具备哪些功能

抽象类是用于强制要求子类必须按照协议中规定的来实现 

然而,python不推崇限制你的语法, 我们可以设计成鸭子类型,既让多个不同类对象具备相同的属性和方法

对于使用者而言,就可以以不变应万变,轻松的使用各种对象

  

原文地址:https://www.cnblogs.com/Gaimo/p/11252447.html