day26 封装、多态、内置函数、反射、动态导入
今日内容
1、封装
什么是封装?
封装从字面意思上看就只将某种东西封起来装好,当我们代码中的某些方法与属性不想让外界进行访问时,就对这些属性进行特殊的处理,使这种属性或者方法不能被外界直接进行访问或者修改,这种方法就称之为封装
但是,在python中没有完全意义的封装,封装只是在内部进行了变形,使其使用原变量名不能进行访问
同时,有些父类的方法,如果不想让子类进行覆盖就将父类的方法设置为私有属性
封装的方法:
在python中如果需要对某个属性或方法进行封装是只需要在变量名前设置为__开头的即可,此时在在外界进行访问时就不能访问这个属性或方法
封装的原理:
我们在进行封装时,实际上是对封装的属性或方法进行了变形,当类进行定义时,如果属性或者方法是以__开头的就会对这个属性进行变形,变形方式为:
在__前面加上_类名变为_类名__属性名或方法名
注意:变形的操作只在定义类时执行一次
在python中,并不会限制用户访问私有属性及方法,私有的属性及方法还是可以被外界访问的,只要自己将方法前面添加_类名就可以访问私有的属性及方法
其实很多时候你去调用一个模块的功能时会遇到单下划线开头的(socket.socket,sys.home,sys._clear_type_cache),这些都是私有的,原则上是供内部调用的
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age p = Person("lee",20)
print(p.name)
# print(p.__age) # AttributeError: 'Person' object has no attribute '__age'
p.__age = 18
print(p.__age) #
print(p.__dict__) # {'name': 'lee', '_Person__age': 20, '__age': 18}
从上例中可以看出:当把属性设置为__开头时就不能在外界直接访问及修改了,如果直接使用 对象.__方法名进行设置,不是对原来的方法进行设置,而是在名称空间直接设置了一个新的变量名
封装的目的
封装不是单纯意义的隐藏,封装会明确的区分内外,在类的内部可以直接使用但是在外部就不可以直接使用
封装的目的:
1、提高安全性:提高安全性主要是针对属性而言的,封装后属性的值不能直接被外界访问及修改,可以保证数据的安全性
2、隔离复杂度:隔离复杂度是针对于方法而言的,我们将类中具体的逻辑私有化,再将其封装到一个方法中供外界访问,这样用户只需要进行一次调用就可以直接访问,对用户而言降低了复杂度
class ATM:
def __card(self):
print('插卡') def __auth(self):
print('用户认证') def __input(self):
print('输入取款金额') def __print_bill(self):
print('打印账单') def __take_money(self):
print('取款') def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__take_money()
self.__print_bill() atm = ATM()
atm.withdraw()
# 插卡
# 用户认证
# 输入取款金额
# 取款
# 打印账单
上述方法对于用户而言只是进行了取款操作,但是在类的内部通过私有方法已经进行了一系列操作
property装饰器
property是一个属性装饰器,可以将方法伪装成属性
实际上,property是一个类,在使用是就是调用这个类产生一个实例化对象,这个对象经常使用的方法有三种:`
getter setter deleter`
其中:
getter在调用property时就会自动调用
setter在设置方法时调用
deleter在删除方法时调用
property使用场景一:供私有属性使用
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age def get_age(self):
print(self.__age) def set_age(self,new_age):
self.__age = new_age
p =Person("lee",18)
p.name
p.get_age()
通过上例中的方法可以进行私有属性的访问及修改,但是这样我们在访问name属性时可以使用 对象.name进行访问,但是访问age属性是就需要使用 对象.get_age() 来进行访问,同样都是属性但是访问方法却不相同,为了使用户对属性的访问方式相同,此时就需要使用 propety 装饰器
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age @property
def age(self):
return (self.__age) @age.setter
def age(self, new_age):
self.__age = new_age @age.deleter
def age(self):
del self.__dict__["_Person__age"] p = Person("lee", 18)
print(p.name)
print(p.age)
p.age = 20
del p.age
print(p.age) # 会报错
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("egon",1.7,80)
# p.weight = 60
# print(p.BMI)
2、多态
什么是多态?
多态就是一种事物的多种形态
在oop中多态就是不同类型的对象可以响应同一种方法,得到不同的响应结果
# 定义一个动物的类
class Animal:
def bark(self):
pass def sleep(self):
pass def run(self):
pass # 定义一个猫类
class Cat(Animal):
def bark(self):
print("喵喵喵") def sleep(self):
print("躺着睡") def run(self):
print("四条腿跑") # 定义一个人类
class Person(Animal):
def bark(self):
print("hi") def run(self):
print("四条腿跑") def sleep(self):
print("躺着睡") # 定义一个狗类
class Dog(Animal):
def bark(self):
print("汪汪汪") def sleep(self):
print("侧躺着睡") def run(self):
print('四条腿跑') # 定义一个管理员类用来管理动物
class ManagementAnimal:
def Manage(self,animal):
animal.bark()
animal.sleep()
animal.run() dog = Dog()
p = Person()
cat = Cat() m = ManagementAnimal()
m.Manage(p)
m.Manage(dog)
m.Manage(cat)
在上例中:
动物类、狗类、猫类、人类等产生的不同对象可以同时调用bark、sleep、run等方法,但是这些方法的执行结果是不相同的,这种就称之为多态
从上述例子可以看出多态的优点:
1、可以是对象的调用更加的灵活,不论对象如何改变,调用对象方法的方式是相同的
2、可以提高程序的扩展性,在创建一个新的动物类是不需要更改Manager的代码就能进行使用
在python中如果想要强制性的规定动物类必须具有这些个属性,可以导入abc模块
import abc class Animal(metaclass=abc.ABCmeta)
@abc.abstractmethod
def bark(self):
pass def sleep(self):
pass
class Cat(Animal):
def sleep(self):
print("正在叫!") cat = Cat()
如果调用了abc模块,那么子类继承后在进行实例化时,如果不将类中含有abstractmethod的方法全部重新定义,就会报错,其中没有abstractmethod的方法不受限制
虽然在Python中可以使用abc模块进行限制,但是python编程更多的是建议,而不是约束
所以python中更多的是建议用户使用鸭子类型
3、内置函数
__str__
_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)
__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())
4、反射
英文中叫反省 (自省)
面向对象中的反省 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;
一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性
反射就是通过字符串来操作对象属性
涉及到的方法:
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....!")
5、动态导入模块
直接写import 称之为静态导入 建立在一个基础上:提前已经知道有这个模块
动态导入 指的是 在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块
import importlib mk = importlib.import_module(m_name) mk 即导入成功的模块
该方式常用在框架中 因为框架设计者不可能提前预知后续需要的模块和类
day26 封装、多态、内置函数、反射、动态导入的更多相关文章
- python之类的多态(鸭子类型 )、封装和内置函数property
一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...
- day28 面向对象:反射,内置函数,类的内置方法
面向对象进阶博客地址链接: http://www.cnblogs.com/Eva-J/articles/7351812.html 复习昨日内容: # 包 # 开发规范 # # hashlib # 登录 ...
- python语法基础-函数-内置函数和匿名函数-长期维护
################## 内置函数 ####################### """ 一共是 68个内置函数: 反射相关的内置函 ...
- 封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块
1,封装 ## 什么是封装 what 对外隐藏内部的属性,以及实现细节,并给外部提供使用的接口 学习封装的目的:就是为了能够限制外界对内部数据的方法 注意 :封装有隐藏的意思,但不是单纯的隐藏 pyt ...
- 绑定与非绑定方法及反射,isinstance和issubclass内置函数
目录 绑定方法与非绑定方法 1.绑定方法 2.非绑定方法(staticmethod) isinstance和issubclass 内置函数 1.isinstance 2.issubclass 反射(面 ...
- Python-老男孩-01_基础_文件IO_函数_yield_三元_常用内置函数_反射_random_md5_序列化_正则表达式_time
Python2.7 缩进统一: 约定 常量 大写 , 变量 小写 判断一个变量在内存中的地址,也能看出是不是一个值 id()函数 >>> x = 'abc' >>&g ...
- python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法
一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...
- 面向对象 反射 和item系列和内置函数和__getattr__和__setattr__
反射 反射主要用在网络编程中, python面向对象的反射:通过字符串的形式操作对象相关的属性.python的一切事物都是对象. 反射就是通过字符串的形式,导入模块:通过字符串的形式,去模块寻找指定函 ...
- Python 面向对象 (补充) , 反射 , 内置函数
面向对象中内置函数 issubclass方法: 检查第一个参数是否是第二个参数的子子孙孙类 返回 : 是一个布尔值 class Base(object): pass class Foo( ...
随机推荐
- MFC 静态文本框
窗体上操作控件内容,需要句柄,在控件处使用鼠标右键——添加变量. DoDataExchange()函数会自动生成代码,把ID与变量绑定(即DDX_Control(pDX, IDC_TEXT, objT ...
- php 一段 shmop
$size = 1024*1024; $shm_key = ftok(__FILE__, 't'); $shm_id = shmop_open($shm_key, "c", 064 ...
- POJ 3177 (Redundant Paths) —— (有重边,边双联通,无向图缩点)
做到这里以后,总算是觉得tarjan算法已经有点入门了. 这题的题意是,给出若干个点和若干条边连接他们,在这个无向图中,问至少增加多少条边可以使得这个图变成边双联通图(即任意两点间都有至少两条没有重复 ...
- JavaScript设计模式—代理模式
代理模式介绍 使用者无权访问目标对象,中间加代理,通过代理做授权和控制 代理(proxy)是一个对象,它可以用来控制对另外一个对象的访问: 代理对象和本体对象实现了同样的接口,并且会把任何方法调用传递 ...
- chrome获取xpath元素-f12工具
Chrome浏览器获取XPATH的方法----通过开发者工具获取 引用源:https://blog.csdn.net/li6727975/article/details/46126079 版权声明 ...
- 在linux环境下使用icepdf或pdfbox将pdf转化成图片是乱码解决
在linux环境下使用icepdf或pdfbox将pdf转化成图片是出现乱码,网上查发下是itextpdf生成pdf引用"STSong-Light"字体而linux环境下没有这个字 ...
- springboot项目的maven的pom.xml文件第一行报错 Unknown Error
springboot项目的maven的pom.xml文件第一行报错 Unknown Error https://blog.csdn.net/mini_jike/article/details/9239 ...
- sentinel备忘
git https://github.com/alibaba/Sentinel https://github.com/dubbo/dubbo-sentinel-supportdubbo http: ...
- 可插拔式后台管理系统(Django)
1.实现效果 研究了下django admin的功能,自己实现了一个简单的可插拔式后台管理系统,方便自定义特殊的功能,而且作为一个独立单独的django app,可以整体拷贝到其他项目中作为后台数据管 ...
- You don't have permission to access / on this server. wampserver3.1.0配置外网访问的问题
参考各种wamp教程后外网仍然不能访问服务器,很是头疼 网上好多wampserver配置都比较久远,最新版本3.1.0的很少,首先打开httpd.conf文件(这部分较简略,详细可以参考其他wamp配 ...