封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块
1,封装
- ## 什么是封装 what
- 对外隐藏内部的属性,以及实现细节,并给外部提供使用的接口
- 学习封装的目的:就是为了能够限制外界对内部数据的方法
- 注意 :封装有隐藏的意思,但不是单纯的隐藏
- python 中属性的权限分为两种:
- 1,分开的
- 没有任何限制,谁都可以访问
- 2,私有的
- 只有当前类本身能够访问
- 默认为公共的
- ##如何封装 how
- 为什么要封装:
- 1,提高安全性 (封装属性)
- 2,隔离复杂度 (封装方法)
- 一个类中分为两种数据,属性和方法:
- 封装属性:
- 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 show_id_card(self):
- # 可以在这里添加额外的任何逻辑代码 来限制外部的访问
- #在类的内部 可以访问
- print(self.__id_card)
- 对私有属性的访问以及修改:
- 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 == '':
- return self.__id_card
- raise Exception('密码错误!')
- #修改被封装的属性,称之为设置器
- def set_id_card(self,new_id):
- #身份证必须是字符串类型
- #长度必须是18位
- if isinstance(new_id,str) and len(new_id) == 18:
- self.__id_card = new_id
- else:
- raise Exception('身份证号码必须是字符串,且长度为18')
- s = Student('rose',10,'man','')
- print(s.get_id_card('')) #
- #设置属性
- s.set_id_card('')
- print(s.get_id_card('')) #222222222222222222
- 什么样的方法应该被封装起来 :
- 当这个对象存在一个机密性的属性 例如 人的身份证 银行卡密码等等,这样属性不应该被外界直接 访问当 ,那就封装起来。
- 一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 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('输入取款金额')
- def __save_record(self):
- print('记录流水')
- a = ATM()
- a.withdraw()
#输入账号和密码
#输入取款金额
#记录流水
2,封装的原理:
- '''
- python 是通过变形的方式来实现的封装
- 如何变形 : 在名称带有双下划线开头的变量名字前添加_类名 如:_Person_id_card
- 当然通过变形后的名字可以直接访问被隐藏的属性 ,但通常不这样做 如: p._Person__id_card
- 变形仅在类的定义阶段发生一次,后续再添加在带有双下划线的任何属性都不会变形,就是普通函数
- '''''
- class Person:
- def __init__(self,name,age,id_card):
- self.name = name
- self.age = age
- self.__id_card = id_card #_Person__id_card
- def get_id_card(self):
- return self.__id_card
- p = Person('rose',20,'')
- print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123'}
- print(p.name)
- p.__id_card = '' #重新开辟了一块空间存储
- print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123', '__id_card': '123'}
- print(p._Person__id_card) #直接强制访问 12321323123123
- p.__gender = 'man'
- print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123', '__id_card': '123', '__gender': 'man'}
3,Property ,setter ,deleter
- Property 作用 : 将一个方法伪装成普通属性
- 为什么用 property : 希望将访问私有属性和普通属性的方式变得一致
- 与property相关的两个装饰器:
- setter : 用点语法 给属性赋值时触发
- 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):
- print(self.__dict__) #{'name': 'owen', 'age': 29, '_Teacher__salary': 88888}
- del self.__dict__['_Teacher__salary']
- t = Teacher('owen',29,88888)
- # del t.salary
- print(t.salary) #
- t.salary = 100000
- print(t.salary) #
- '''
- 总结:
- 被封装的属性在访问时,需要调用方法,而普通属性直接点就OK,这样一来对于对象的使用者而言
- 必须知道要访问的属性,是私有还是公开,然后在调用对应的方法.用起来就会比较麻烦
- 此时,我们的目的就是让访问私有属性和访问普通属性的方式一样通过点来调用
- property装饰器:就是用来将一个方法伪装成属性,可以直接通过点来调用
- '''
- '''
- property的另一种使用场景,计算属性
- 什么是计算属性:
- 一个属性它的值不是固定死的,而是通过计算产生的
- '''''
- 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('BMI 不支持自定义.....')
- p = Person('owen',1.78,60)
- print(p.BMI) #18.93700290367378
- p.weight = 90
- print(p.BMI) #28.40550435551067
- #被封装的内容(私有的) 不可以被继承
- class A:
- __name = 'rose' #变形后 _A__name
- def __say_hi(self):
- print('A say hi')
- class B(A):
- def test(self):
- # print(super().__name) #变形后 _B__name 在哪个类就以哪个类变形
- print(A._A__name) #通过super()不能使用父类的私有属性,可以通过类名直接访问
- b = B()
- b.test()
4,多态
- """
- 多态 :
- 多态不是一个具体的技术 或代码
- 指的是 多个不同类型对象 可以响应同一个方法 ,产生不同结果
- 某种事物具备多个不同形态
- 例如 水: 气态 固态 液态
- 动物: 人 猫 猪
- 汽车人: 汽车 飞机 人型
- OOP中 标准解释: 多个不同类型对象 可以响应同一个方法 并且产生不同结果
- 多态的带来的好处:
- 只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的,以不变应万变 ,提高了灵活性
- 提高扩展性
- 如何实现多态:
- 鸭子类型 就是典型的多态 多种不同类型 使用方法一样
- """
- # import abc
- # class Animal(metaclass=abc.ABCMeta):
- #
- # @abc.abstractmethod
- # def bark(self):
- # pass
- #
- # @abc.abstractmethod
- # def run(self):
- # pass
- #
- # @abc.abstractmethod
- # def sleep(self):
- # pass
- 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("侧躺着睡!")
- person1 = Person()
- cat1 = Cat()
- pig1 = Pig()
- person1.sleep()
- cat1.sleep()
- pig1.sleep()
- # 如果没有多态 需要分别学习 person cat pig 的不同使用方法 这对于使用者而言太麻烦了
- # 一个用来管理动物的方法 只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
- 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)
- class Dog():
- def bark(self):
- print("汪汪汪...")
- def run(self):
- print("四条腿跑!")
- def sleep(self):
- print("趴着睡!")
- dog1 = Dog()
- management_animal(dog1)
- class Fish():
- def bark(self):
- print("超声波...")
- def run(self):
- print("游来游去.....")
- def sleep(self):
- print("睁眼睡觉....")
- f = Fish()
- management_animal(f)
- # 无处不在的多态
- # def MY_LEN(obj):
- # return obj.__len__()
- #
- # print(MY_LEN("abcdefg"))
- # print(MY_LEN([1,2,3,4]))
- # print(MY_LEN({"name":123}))
- print(len(""))
5,常用的内置函数 ,__str__ , __del__
- __str__ :
- '''
- 类中的__str__:
- 该方法在object中有定义,默认行为,返回对象类型以及地址
- 在将对象转为字符串时执行
- 注意:返回值必须为字符串类型
- 子类可以覆盖该方法来完成,对打印内容的自定义
- '''''
- 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)
- '''#在打印前都会先将要打印的内容转为字符串,通过调用__str__函数'''
- print(p) #my name is rose.age is 20
- str(p) #str run
- '''
- __del__:
- 当对象被删除前会自动调用该方法
- 声明的时候会删除对象?
- 1,程序运行结束,解释器退出,将自动删除所有数据
- 2,手动调用del 时也会删除对象
- 注意: 该函数不是用来删除对象的
- 使用场景:
- 当你的对象在创建时,开启了不属于解释器的资源 ,例如: 打开了一个文件
- 必须保证当前对象被删除时,同时关闭额外的资源,如:文件
- 也称之为析构函数(一个个拆分,解析) 构造 的反义词
- 构造:指的是从无到有
- 析构:指的是有到无
- 简单的说就对象所有数据全部删除
- 总结:__del__该函数 用于在对象删除前做的一些清理操作(或提醒)
- '''''
- #假设要求每一个person对象都要绑定一个文件
- class Person:
- def __init__(self,name,path):
- self.name = name
- self.file = open(path,encoding='utf-8')
- #读取数据的方法
- def read_data(self):
- return self.file.read()
- def __del__(self):
- print('del run1') #当程序执行完后才会执行这个
- self.file.close()
- p = Person('owen','封装方法.py')
- print(p.read_data())
6,反射
- 英文中叫反省 (自省)
- 面向对象中的反省 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;
- 一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性
- ## 反射就是通过字符串来操作对象属性
- 涉及到的方法:
- hasattr 判断是否存在某个属性
- getattr 获取某个属性的值
- setattr 新增或修改某个属性
- delattr 删除某个属性
- 案例1:
- import os
- class Student:
- def __init__(self,name):
- self.name = name
- def www(self):
- print('')
- stu = Student('rose')
- #反射的四个方法
- print(hasattr(stu,'name')) #True
- print(getattr(stu,'name')) #rose
- setattr(stu,'name','')
- print(getattr(stu,'name')) #
- delattr(stu,'name')
- print(hasattr(stu,'name')) #False
- print(hasattr(stu,'www')) #True
- 案例2:
- 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) #绑定方法: <bound method MY_CMD.dir of <__main__.MY_CMD object at 0x0000021FFF8765F8>>
- method()
- else:
- print('sorry this method is not exists....!')
7,动态导入模块:
- '''
- 直接写import 称之为静态导入,建立在一个基础时,提前已经知道有这个模块
- 动态导入:指的是在需要的任何时候,通过指定字符类型,包名称来导入需要的模块
- import importlib
- mk = importlib.import_module(m_name)
- mk 即导入成功的模块
- '''''
- #动态导入模块.py
- import importlib
- m_name = input('请输入要导入的模块名称:').strip()
- mk = importlib.import_module(m_name)
- print(mk) #<module '计算属性' from 'D:\\Python_Project\\ClassRoom\\day26\\练习\\计算属性.py'>
- from day26.练习.build_house import conf
- print(conf)
- #build_house/conf.py
- decoration = [
- 'build_house.my_decoration.Table',
- 'build_house.my_decoration.Light',
- 'build_house.my_decoration.Bed',
- 'other_decoration.Sofa'
- ]
- #build_house/core.py
- import importlib
- from day26.练习.build_house import conf
- def building():
- print('毛坯房建造完成.....')
- #读取用户提供配置信息,来加载用户所需要的一系列装饰品
- for cls_info in conf.decoration:
- # print(cls_info)
- #切割类名和模块路径
- m_name,cls_name = cls_info.rsplit('.',1)
- # print(m_name,cls_name) #build_house.my_decoration Table
- #导入模块
- mk = importlib.import_module(m_name)
- print(mk)
- #从模块中获取类
- if not hasattr(mk,cls_name):
- continue
- cls = getattr(mk,cls_name)
- obj = cls()
- print(obj)
- building()
- #build_house/my_decoration.py
- class Table:
- pass
- class Light:
- pass
- class Bed:
- pass
封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块的更多相关文章
- day26 封装、多态、内置函数、反射、动态导入
今日内容 1.封装 什么是封装? 封装从字面意思上看就只将某种东西封起来装好,当我们代码中的某些方法与属性不想让外界进行访问时,就对这些属性进行特殊的处理,使这种属性或者方法不能被外界直接进行访问或者 ...
- python之类的多态(鸭子类型 )、封装和内置函数property
一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...
- python面向对象的多态-类相关内置函数-类内置魔法函数-迭代器协议-上下文管理-04
多态 一种事物具备不同的形态 例如:水 --> 固态.液态.气态 多态:# 多个不同对象可以相应同一个对象,产生不同的结果 首先强调,多态不是一种特殊的语法,而是一种状态,特性(多个不同对象可以 ...
- day15生成器send方法,递归,匿名函数,max结合匿名工作原理,常用的内置函数
复习 ''' 1.带参装饰器 - 自定义 | wraps def wrap(info) def outer1(func): from functools import wraps @wraps(fun ...
- day30 继承、派生与多态,类中方法和内置函数
目录 一.多继承出现的问题(mixins机制) 二.派生与方法重用 三.多态 1 什么是多态 2 为什么要有多态 3 python中多态的鸭子类型 四.绑定方法与非绑定方法 1 绑定方法 1.1对象的 ...
- Python类总结-封装(Property, setter, deleter)
Property #property #内置装饰器函数,只在面向对象中使用 from math import pi class Circle: def __init__(self,r ): self. ...
- 面向对象_内置函数 property
property 将方法伪装成为属性,可以不用加上()就可以调出其属性. 但是用__dict__,不能调出此属性 from math import pi class Circle: def __ini ...
- Python内置函数之-property
property 是一个内置的装饰器函数,只在面向对象中使用 求一个圆的周长和面积 # 周长和面积都是通过类的方法得到from math import pi class Cricle: def __i ...
- Python内置函数property()使用实例
class Shuxing(): def __init__(self, size = 10): self.size = size def getSize(self): print('getSize') ...
随机推荐
- Apache Atlas是什么?
不多说,直接上干货! Apache Atlas是Hadoop社区为解决Hadoop生态系统的元数据治理问题而产生的开源项目,它为Hadoop集群提供了包括数据分类.集中策略引擎.数据血缘.安全和生命周 ...
- Unity3d中3D Text对模型的穿透显示
昨晚,好友在电话里问我在Unity3d中使用3D Text,不想让其穿透模型显示,即想让场景中的3D Text与模型有正确的遮挡关系,怎么解? 今早谷歌上查了查,明白了原因,因为3D Text的默认材 ...
- <Android 应用 之路> 天气预报(三)
昨天介绍了基本的载入界面,今天介绍下天气信息显示界面的代码 基本ListView显示 搜索框,查询城市 上一篇文章中,载入界面通过showWeatherInfo()方法跳转到天气信息显示界面 priv ...
- Eucalyptus——EC2的开源实现(转载)
Eucalyptus[22]是加利福尼亚大学的 Daniel Nurmi 等人实现的,是一个用于实现云计算的开源软件基础设施.Eucalyptus 是 Amazon EC2 的一个开源实现,它与 EC ...
- SpringMVC+Thymeleaf 简单使用
一.简介 1.Thymeleaf 在有网络和无网络的环境下皆可运行,而且完全不需启动WEB应用,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果.浏览器解释 h ...
- self & this 上下文
对象:指向对象的首地址: 函数:代表了函数运行的主要上下文: 内部:在类的内部使用. self Within the body of a class method, self refers to th ...
- [论文理解] CornerNet: Detecting Objects as Paired Keypoints
[论文理解] CornerNet: Detecting Objects as Paired Keypoints 简介 首先这是一篇anchor free的文章,看了之后觉得方法挺好的,预测左上角和右下 ...
- C#之winform实现文件拖拽功能【转】
将一个文件拖拽到窗体的某个控件时,将该控件的路径显示在该控件上,只要拿到了路径自然可以读取文件中的内容了 将一个控件的属性AllowDrop设置为true,然后添加DragDrop.DragEnter ...
- Web服务器 --> 基于HTTP的网站开发
经过几十年的发展,已经出现几个成熟的处理HTTP的知名的Web服务器.这些服务器可以解析(handle)HTTP,当Web服务器接收到一个HTTP请求时,会根据配置的内容返回一个静态HTML页面或者调 ...
- js实现23种设计模式(收藏)
js实现23种设计模式 最近在学习面向对象的23种设计模式,使用java 和 javascript 实现了一遍,但是因为目前大三,还没有比较正规的大项目经验,所以学习的过程种我觉得如果没有一定的项目经 ...