python_day26-封装 多态 __str__ __del__ 反射 动态导入

# 1 封装
# 什么是封装 :对外部隐藏属性和方法  给外部提供使用的接口
# 目的:限制外部对内部数据的访问  因为有些数据是机密的  不方便对外透露
#  如何封装:  __开头的语法  分为封装属性  和 封装方法
# 封装的好处:  封装属性--提高安全性   封装方法:提高便利性

# 封装属性

'''
class Student:
    def __init__(self,name,age,id_card):
        self.name = name
        self.age = age
        self.__id_card = id_card  # 外部就无法通过.id_card 和 .__id_card
    def show_id_card(self):
        print(self.__id_card)

stu = Student('tom',18,'xxxxxxxx')
print(stu.name)  # tom
print(stu.age)  # 18
# print(stu.__id_card)   是没有这个的
stu.show_id_card()  #  xxxxxxxx
'''

#  对私有属性的访问以及修改
'''
class Student:
    def __init__(self,name,age,id_card):
        self.name = name
        self.age = age
        self.__id_card = id_card  # 外部就无法通过.id_card 和 .__id_card

    def get_id_card(self,pwd):  # 访问被封装的属性  称之为访问器  可以为访问添加条件
        if pwd == '123':
            return self.__id_card
        else:
            print('密码错误')

    def set_id_card(self,new_id_card): # 修改被封装的属性称之为设置器
        # 身份证必须是字符 且 是18位
        if isinstance(new_id_card,str) and len(new_id_card) == 18:
            self.__id_card = new_id_card
        else:
            print('新身份证不符合规定')


stu = Student('tom',18,'123456789012345678')
stu.get_id_card('wsx')  # 密码错误
stu.set_id_card('123456789123456789')  # 无结果
'''

# 给方法封装  说明这方法可以被内部访问 不应该被外界访问
"""
class ATM:
    def withdraw(self):
        self.__user_auth()
        self.__input_money()
        self.__save_record()
    # 输入账号和密码
    # 显示余额
    # 输入取款金额
    # 保存记录
    def __user_auth(self):
        print('输入用户名和密码')

    def __input_money(self):
        print('余额为1000000,输入取款金额!')

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

atm = ATM()
atm.withdraw()  #  提现只需要调用withdraw就可以了  不需要一步一步去操作其他三个步骤 简化了外部操作
"""

# 2:property装饰器 的 用途1
# 作用:将方法伪装成普通属性
# 为什么要用property  希望将私有属性的访问方式和普通属性一致  普通属性 点语法
# 与property相关的 两个装饰器
# setter
# ​    用点语法 给属性赋值时触发
#
# deleter
# ​    用点语法删除属性时触发
# 案例
'''
class Teacher:
    def __init__(self,name,age,salary):
        self.name = name
        self.age = age
        self.__salary = salary   #  s实质是在名称空间里换名字为 _Teacher__salary

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

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

    @salary.deleter
    def salary(self):
        del self.__dict__['_Teacher__salary']  # 删除老师薪水部分


a = Teacher('jeck',18,50)  # 这是访问私有属性
print(a.salary)   # 50

a.salary=10  # 赋值时运用 setter
print(a.salary)  # 10

del a.salary  # 已删除salary部分
# print(a.salary)  这时打印会报错的
'''

# property装饰器 的 用途2 :计算属性
# 有些属性不是固定的  是需要计算出来的 这是也可以用到property
# 例如计算BMI  体质指数(BMI)=体重(kg)÷身高^2(m)
'''
class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height

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

    @BMI.setter
    def BMI(self,new_bmi):
        print('bmi不支持自定义')
p = People('egon',80,1.7)
print(p.BMI) # 27.68166089965398
p.BMI = 10  # 运行这步  不会更改值   bmi不支持自定义
print(p.BMI) #  27.68166089965398 结果还是这个不会变的  计算属性时 setter 不受用
# 多态
# 定义:多个不同类型对象可以响应同一个产生不同的结果 *****
# 好处: 只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的   以不变应万变   提高了灵活性 提高扩展性

# 如果没有多态  需要分别学习 person  cat pig 的不同使用方法 这对于使用者而言太麻烦了
# 人 和 猫  和猪都有一些相同的技能 会说话 会跑 会睡觉  但是这三种技能动物都拥有  那么可以运用多态建立一个动物三种函数
class Person:
    def bark(self):
        print('hello')

    def run(self):
        print('两腿跑')

    def sleep(self):
        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()

# 来了一堆动物
person1 = Person()
cat1 = Cat()
pig1 = Pig()

management_animal(person1)
management_animal(cat1)
management_animal(pig1)
# 类中的 内置函数  __str__
"""
类中的__str__
    该方法在object中有定义 默认行为 返回对象类型以及地址  <__main__.Person object at 0x0000016F450C7390>
    在将对象转为字符串时执行
    注意:返回值必须为字符串类型
    子类可以覆盖该方法来完成 对打印内容的自定义
"""

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # 将对象转换为字符串时执行
    def __str__(self):
        print("str run")
        return "my name is %s , age is %s" % (self.name,self.age)


p = Person("rose",20)
# print(p)  #在打印前都会现将要打印的内容转为字符串  通过调用__str__函数

str(p)  # str run



# 类中__del__
"""
__del__
当对象被删除前会自动调用 该方法
声明时候会删除对象?
    1.程序运行结束 解释器退出 将自动删除所有数据
    2.手动调用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()
# p = Person("jack")
# a = 10
# f = open("test.txt")
# print(f.read())
# f.close()
p2 = Person("rose","本周内容")
print(p2.read_data())  # 具体看运行结果
'''


# 反射 面向对象中指的就是  对象必须具备发现自己属性以及修改自己属性的能力
# 因为在创建初期的属性可能不符合后期要求 则需要删除或增加或修改属性

# 四个方法
# hasattr  判断是否存在这个属性
# getattr  取得这个属性的值
# setattr  增加或修改某属性的
# delattr  删除某个属性
# 案例
"""
import os
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('不存在这个方法')

#  可输入 dir 和 ipconfig 两个方法
"""
# 动态导入
# import 是静态导入 是提前知道有这个模块
# 动态导入:在需要的时候 通过指定字符串形式来导入需要的模块
# 语法
import importlib
mk = importlib.import_module(m_name) # m_name 指的就是模块名
print(mk)
# mk 就是导入的模块

猜你喜欢

转载自www.cnblogs.com/wakee/p/10897580.html
今日推荐