面向对象三

一.封装

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

目的:就是为了能够限制外界对内部数据的访问

封装的语法:__id_card  在属性前加__

封装的优点:

封装属性

1.提高安全性

封装方法

2.隔离复杂度

封装属性的案例:

 1 class Student:
 2 
 3     def __init__(self,name,age,gender,id_card):
 4         self.name = name
 5         self.age = age
 6         self.gender = gender
 7         self.__id_card = id_card
 8 
 9     def show_id_card(self):
10         # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
11         
12         #在类的内部 可以访问
13         print(self.__id_card)

对私有属性的访问以及修改:

 1 class Student:
 2     def __init__(self,name,age,gender,id_card):
 3         self.name = name
 4         self.age = age
 5         self.gender = gender
 6         self.__id_card = id_card
 7 
 8     # 访问被封装的属性  称之为访问器
 9     def get_id_card(self,pwd):
10         # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
11         # 在类的内部 可以访问
12         if pwd =="123":
13             return self.__id_card
14         raise Exception("密码错误!")
15 
16 
17     # 修改被封装的属性   称之为设置器
18     def set_id_crad(self,new_id):
19         # 身份证必须是字符串类型
20         # 长度必须是18位
21         if isinstance(new_id,str) and len(new_id) == 18:
22             self.__id_card = new_id
23         else:
24             raise Exception("身份证号码 必须是字符串 且长度必须为18!")

封装的原理:

python是通过 变形的方式来实现的封装
如何变形 在名称带有双下划线开头的变量名字前添加_类名  如_Person__id_card
当然通过变形后的名字可以直接访问被隐藏的属性  但通过不应该这么做
变形仅在类的定义阶段发生一次 后续再添加的带有双下划线的任何属性都不会变形  就是普通属性

Property

作用: 将一个方法伪装成普通属性

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

与property相关的 两个装饰器

setter

用点语法 给属性赋值时触发

deleter

用点语法删除属性时触发

 1 class Teacher:
 2     def __init__(self,name,age,salary):
 3         self.name = name
 4         self.age = age
 5         self.__salary = salary
 6 
 7     @property  # getter   # 用于访问私有属性的值   也可以访问普通属性
 8     def salary(self):
 9         return self.__salary
10 
11     @salary.setter   # 用来设置私有属性的值  也可以设置普通属性
12     def salary(self,new_salary):
13         self.__salary = new_salary
14 
15     @salary.deleter # 用来设置私有属性的值  也可以删除普通属性
16     def salary(self):
17         # print("can not delete salary!")
18         del self.__dict__["_Teacher__salary"]

 

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

一个属性 它的值不是固定死的 而是通过计算动态产生的 BMI

 1 class Person:
 2     def __init__(self,name,height,weight):
 3         self.name = name
 4         self.height = height
 5         self.weight = weight
 6         # self.BMI = weight / (height ** 2)
 7 
 8     @property
 9     def BMI(self):
10         return self.weight / (self.height ** 2)
11 
12     @BMI.setter
13     def BMI(self,new_BMI):
14         print("BMI 不支持自定义.....")
15 
16 
17 p = Person("egon",1.7,80)
18 print(p.BMI)
19 p.BMI = 10

三.多态

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

指的是 多个不同类型对象 可以响应同一个方法 ,产生不同结果

OOP中 标准解释: 多个不同类型对象 可以响应同一个方法  并且产生不同结果

多态的带来的好处:只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的   以不变应万变   提高了灵活性,提高扩展性

 1 class Cat():
 2     def bark(self):
 3         print("喵喵喵")
 4     def run(self):
 5         print("四条腿跑!")
 6     def sleep(self):
 7         print("趴着睡!")
 8         
 9 class Pig():
10     def bark(self):
11         print("哼哼哼!")
12     def run(self):
13         print("四条腿跑!")
14     def sleep(self):
15         print("侧躺着睡!")
16 
17 # 一个用来管理动物的方法   只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
18 def management_animal(animal):
19     print("==================正在溜%s=============" % animal.__class__.__name__)
20     animal.bark()
21     animal.run()
22     animal.sleep()

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

__str__:在将对象转为字符串是执行

在打印前会将要打印的内容全部转为字符串,默认返回对象类型和地址

 

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

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

使用场景
当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件
必须保证当对象被删除时 同时关闭额外的资源  如文件

五.反射

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

涉及到的办法:

hasattr 判断是否存在某个属性

getattr    获取某个属性的值

setattr    新增或修改某个属性

delattr 删除某个属性

 1 class MY_CMD:
 2 
 3     def dir(self):
 4         os.system("dir")
 5 
 6     def ipconfig(self):
 7         os.system("ipconfig")
 8 
 9 cmd = MY_CMD()
10 
11 while True:
12     name = input("请输入要执行的功能:")
13     if hasattr(cmd,name):
14         method = getattr(cmd,name)
15         print(method)
16         method()
17     else:
18         print("sorry this method is not exists....!")

七.动态模块导入

import 称之为静态导入  建立在一个基础上:提前已经知道有这个模块
动态导入  指的是  在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块

导入方式:import importlib

mk = importlib.import_module(m_name)
mk 即导入成功的模块

posted @ 2019-05-20 21:32  坚信会有奥特曼~  阅读(122)  评论(0)    收藏  举报