day_26,面向对象之,封装 -多态

封装

什么是封装 what

对外部隐藏内部的属性,以及实现细节 , 给外部提供使用的接口

注意:封装有隐藏的意思,但不是单纯的隐藏

学习封装的目的.就是为了能够限制外界对内部数据的访问

python中属性的权限分为两种

1.公开的

没有任何限制 谁都能访问

2.私有的

只有当前类本身能够访问

默认为公共的

如何封装 how

在想要隐藏的属性或方法名前加两个下划线__

为什么要封装 why

1.提高安全性

  封装属性

2.隔离复杂度

  封装方法

 

 类中分为两种数据,属性和方法

封装属性:

class Student:
    def __init__(self,name,age,id_card):
        self.name = name
        self.age = age
        self.__id_card = id_card


    def show_id_card(self):
        # 在这里可以添加额外的任何逻辑代码,来限制外部的访问

        # 在类的内部 可以访问
        print(self.__id_card)
View Code
对私有属性的访问以及修改
class Student:
    def __init__(self,name,age,gender,id_card):
        self.name = name
        self.age = age
        self.gender = gender
        self.__id_card = id_card

    # 访问被封装的属性  称之为访问器
    def get_id_card(self,pwd):
        # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
        # 在类的内部 可以访问
        if pwd =="123":
            return self.__id_card
        raise Exception("密码错误!")


    # 修改被封装的属性   称之为设置器
    def set_id_crad(self,new_id):
        # 身份证必须是字符串类型
        # 长度必须是18位
        if isinstance(new_id,str) and len(new_id) == 18:
            self.__id_card = new_id
        else:
            raise Exception("身份证号码 必须是字符串 且长度必须为18!")
View Code

那么什么样的方法应该被封装起来呢.

  一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 user_auth等...

class ATM:

    def withdraw(self):
        self.__user_auth()
        self.__input_money()
        self.__save_record()
        # 输入账号和密码
        # 显示余额
        # 输入取款金额
        # 保存记录

    def __user_auth(self):
        print("请输入账号密码....")

    def __input_money(self):
        print("余额为100000000,请输入取款金额!")

    def  __save_record(self):
        print("记录流水....")

封装的原理

  python是通过变形的方式来实现的封装

  在名称带有双下划线开头的变量名字前添加_类名,

当然通过变形后的名字可以直接访问被隐藏的属性 但通过不应该这么做
变形仅在类的定义阶段发生一次 后续再添加的带有双下划线的任何属性都不会变形 就是普通属性

什么时候用 where

封装属性

  当这个对象存在一个机密性的属性.例如人的身份证,银行卡密码,等等,这些属性不应该被外部直接访问到,那就封装起来.

 

下面是Property

他的作用是讲一个方法伪装成普通属性.

为什么用property,希望将访问私有属性和普通属性的方式变得一致.

与property相关的三个装饰器

@property 就是在需要伪装的哪个方法上添加这个装饰器,调用这个方法 就和访问属性一样了 不需要加括号

 

@前面@property的那个方法名.setter

  这个是给那个方法重新赋值的时候触发

 

@前面@property的那个方法名.deleter

  用点语法删除属性的时候触发

class Teacher:
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.__salary = salary

    @property  # getter  用于访问私有属性的值  ,也可以访问普通属性
    def salary(self):
        return self.__salary

    @salary.setter    # 用来设置私有属性的值.也可以设置普通属性
    def salary(self, new_salary):
        self.__salary = new_salary

    @salary.deleter    # 用来删除私有属性.也可以删除普通属性
    def salary(self):
        del self.__dict__['_Teacher__salary']
案例1

property的另一种使用场景.计算属性

什么是计算属性.一个属性.他的值不是固定死的.而是通过计算动态产生的,

比如BMI

class Person:
    def __init__(self,name,height,weight):
        self.name = name
        self.height = height
        self.weight = weight
        #self.BMI = weight / (height ** 2) #这样就不合适了

    @property
    def BMI(self):
        return self.weight / (self.height ** 2)

    @BMI.setter
    def BMI(self,new_BMI):
        print('不支持自定义')

多态

多态不是一个具体的技术或代码

多态就是某种事物的多个不同形态

标准解释 是 多个不同类型的对象.可以相应同一个方法, 并且产生不同结果

多态带来的好处是

  只需要学习基类中的使用方法即可,不需关心具体具体哪一个类.也不用关心怎么实现的. 提高了灵活性 提高了扩展性

 

  如何实现多态: 鸭子类型就是典型的多态,多种不同类型,使用方法一样

class Cat():
    def bark(self):
        print("喵喵喵")
    def run(self):
        print("四条腿跑!")
    def sleep(self):
        print("趴着睡!")
        
class Pig():
    def bark(self):
        print("哼哼哼!")
    def run(self):
        print("四条腿跑!")
    def sleep(self):
        print("侧躺着睡!")

# 一个用来管理动物的方法   只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
def management_animal(animal):
    print("==================正在溜%s=============" % animal.__class__.__name__)
    animal.bark()
    animal.run()
    animal.sleep()

然后是内置函数

类中的__str__
该方法在object中有定义 默认行为 返回对象类型以及地址  #<__main__.Person object at 0x0000016F450C7390>
在将对象转为字符串时执行
注意:返回值必须为字符串类型
子类可以覆盖该方法来完成 对打印内容的自定义,可以自定义为返回一个对象的基本信息

__del__

__del__
当对象被删除前会自动调用 该方法

1.程序运行结束 解释器退出 将自动删除所有数据
2.手动调用del 时也会删除对象

注意:该函数不是用来删除对象的

使用场景
当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件
必须保证当对象被删除时 同时关闭额外的资源 如文件,操作对象中, 无法预知何时关闭这个外部资源,所以就要用到了__del__

这个对象被删除了,就自动执行该方法.同时可以在该方法内定义关闭这个系统资源


也称之为析构函数 构造 的反义词
构造 指的是从无到有
析构 值从有到无
简单的说就对象所有数据全部删除


总结:__del__该函数 用于 在对象删除前做一些清理操作

# 假设要求每一个person对象都要绑定一个文件
class Person:
    def __init__(self,name,path,mode="rt",encoding="utf-8"):
        self.name = name
        self.file = open(path,mode,encoding=encoding)



    # 读取数据的方法
    def read_data(self):
        return self.file.read()


    def __del__(self):
        print("del run!")
        self.file.close()
View Code

反射

英文中叫反省,(自省)

面向对象中的反省 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;

一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性

通俗的讲反射就是通过字符串来操作对象属性

四个方法

hasattr后面给一个对象 在给一个字符串形式的属性名  判断这个属性在不在对象中

getattr (对象名,属性名)获取某个属性的值

setattr (对象名,属性名,新的值)新增或修改某个属性

delattr (对象名,属性名)删除某个属性

class MY_CMD:

    def dir(self):
        os.system("dir")

    def ipconfig(self):
        os.system("ipconfig")

cmd = MY_CMD()

while True:
    name = input("请输入要执行的功能:")
    if hasattr(cmd,name):
        method = getattr(cmd,name)
        print(method)
        method()
    else:
        print("sorry this method is not exists....!")
View Code

动态导入模块

直接写input 称之为静态导入,建立在一个基础上,提前已经知道有这个模块

动态导入 指的是在需要的任何时候 通过制定字符串类型的包名称来导入需要的模块

import importlib

mk = importlib.inport_module(模块名)

mk 就是导入成功的模块

该方式常用在框架中,因为框架设计社不可能提前预知后续需要的模块和类

所以需要加载配置文件里的, 配置文件里的都是字符串,

转载于:https://www.cnblogs.com/jixu/p/10896553.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值