python学习之面向对象(四)
6.9 反射
反射是非常重要的内置函数之一。
反射是通过字符串去操作对象相关的属性,这里的对象包括:实列,类,当前模块,其他模块。
主要的四个函数:
查看: hasattr(对象,待查内容的字符串形式) 判断有没有,返回True或者False
获取: getattr(对象,要获取的内容的字符串形式,获取不到时的返回值)
增加: setattr(对象,要增加的内容的字符串形式)
删除: delattr(对象,要'删除的内容的字符串形式)
6.9.1 实例化中使用
class LOL:place = '召唤师峡谷'def __init__(self,name,role):self.name = nameself.role = roledef equip(self):print('装备什么')gailun = LOL('盖伦','战士')
print(gailun.name)print(hasattr(gailun,'name'))
print(getattr(gailun,'name'))
print(getattr(gailun,'team','没有此属性'))setattr(gailun,'team','德玛西亚')
print(getattr(gailun,'team','没有此属性'))
print(gailun.__dict__)delattr(gailun,'team')
print(getattr(gailun,'team','没有此属性'))# 通过hasattr判断,通过getattr获取,来操作对象的属性和方法
if hasattr(gailun,'equip'): #判断对象里面有没有print(getattr(gailun,'equip')) #若果有,看拿到的是什么getattr(gailun,'equip')() #操作对象的方法
6.9.2 类中使用
class LOL:place = '召唤师峡谷'def __init__(self,name,role):self.name = nameself.role = roledef equip(self):print(self)print('装备什么')gailun = LOL('盖伦','战士')print(hasattr(LOL,'place'))
print(hasattr(LOL,'equip'))
getattr(LOL,'equip')(gailun)
6.9.3 当前脚本中使用
class LOL:place = '召唤师峡谷'def __init__(self,name,role):self.name = nameself.role = roledef equip(self):print(self)print('装备可以加强属性')def func1():print('in func1')
def func2():print('in func2')
def func3():print('in func3')# 获取当前脚本并把它赋值给一个变量
import sys
this_module = sys.modules[__name__] #当前脚本这个对象
if hasattr(this_module,'func1'):getattr(this_module,'func1')()cla = getattr(this_module,'LOL') #可以获取当前脚本中的类
cla.equip(cla)
nvjing = cla('凯特琳','射手')
print(cla)
print(nvjing)
print(nvjing.__dict__)# 将以上函数的函数名的字符串形式放到列表中
l = [f"func{i}" for i in range(1,4)]
for item in l: # 利用getattr运行l列中的函数getattr(this_module,item)(
6.9.4 其他模块中使用
在另一个py文件中,设置
# 反射2.py
def fun1():print('in fen1')
aa = 'aa'
在本文件中调用反射2.py中的函数
import 反射2 as other
getattr(other,'fun1')()
6.9.5 场景使用
class Auth:def login(self):print('登录函数')def register(self):print('注册函数')def exit(self):print('退出...')obj = Auth()
while 1:func_name = input('请输入选择:').strip()if hasattr(Auth,func_name):getattr(Auth,func_name)(obj)
6.10 函数与方法的判断
该节旨在体验双下发放的触发情况,所以使用print和return来帮助提示相关方法的执行
通过名称
通过名称可以大致判断
def func1():passclass A:def func(self):passprint(func1)
obj = A()
print(obj.func)
# 输出信息中含有function的就是函数
# 输出的信息中含有bound method的就是方法
通过type模块验证
from types import FunctionType
from types import MethodTypedef func():pass
class A:def func(self):pass
obj = A()
print(isinstance(func,FunctionType)) #True
print(isinstance(func,MethodType)) #False
print(isinstance(A.func,FunctionType)) #True func在类中是函数
print(isinstance(obj.func,FunctionType)) #Flase
print(isinstance(obj.func,MethodType)) #True func在对象中是方法
定义在类中的共有函数,在类中是函数,在对象中是方法
类的静态方法是函数
类方法是一种方法,静态方法是一种函数
对于写在类内部的静态方法实际上是函数,而类方法就是一种方法
from types import FunctionType
from types import MethodTypeclass A:@classmethoddef func1(cls):pass@staticmethoddef func2(self):pass
obj = A()print(isinstance(A.func1,FunctionType)) #False
print(isinstance(A.func1,MethodType)) #True
print(isinstance(obj.func1,FunctionType)) #False
print(isinstance(obj.func1,MethodType)) #True
print(isinstance(A.func2,FunctionType)) #True
print(isinstance(A.func2,MethodType)) #False
print(isinstance(obj.func2,FunctionType)) #True
print(isinstance(obj.func2,MethodType)) #False
函数与方法的区别
函数是显式传递数据,俗话说,函数一般需要传参
函数与对象无关
方法中的数据是隐式传递数据
方法可以操作类内部的数据
方法是跟对象相关的
6.11 双下方法
双下方法主要是针对开发python语言的设计使用的,要慎用。
双下方法是具有特殊意义的方法,其执行方式也比较特殊,不同的双下方法有不同的触发方式。
__len__
方法
一个对象之所以能够使用len()函数,根本原因是该对象的父类中含有__len__
函数,在使用len()时,类中的__len__
函数就会执行,并返回一个int值给调用者。
class A:def __len__(self):print('aaa')return 1obj = A()
print(len(obj))
__hash__
方法
能够使用hash()函数的对象的父类内含有__hash__
函数,并由hash()触发
class A:aa = 'aa'def __hash__(self):print('正在执行hash函数')return 1
obj = A()
print(hash(obj))
__repr__
方法
如果类中定义了__repr__
函数,repr对象时,默认输出该函数的返回值
class A:def __init__(self):passdef __repr__(self):return '输出__repr__的返回值'obj = A()
print(repr(obj))
print('%r' %obj)
__str__
方法**
如果类中定义了__str__
函数,print对象时,默认输出该函数的返回值
class A:def __init__(self):passdef __str__(self):return '输出__str__的返回值'obj = A()
print(obj)
print('%s' %obj)
__call__
方法**
如果类中定义了__call__
函数,实例化对象后,对象()或者A()()就能触发该函数
class A:def __call__(self):print('可以返回很多的内容,形式多样')
obj = A()
print(obj())
A()()
__del__
方法**
析构方法,当对象在内存中被释放时,自动触发执行。
python本身具有垃圾回收机制,大多数情况下我们不必要去关心内存的分配与释放,该函数略显鸡肋
class A:def __del__(self):print('清空内存')
obj = A()
del obj
如果该程序运行结束,即使没有使用del也会触发__del__
__eq__
方法
进行 == 比较时,就会触发该方法
class A:def __init__(self):self.aa = 11self.bb = 22def __eq__(self,obj):if self.aa == obj.aa and self.bb == obj.bb:print('正在执行__eq__')
obj1 = A()
obj2 = A()
print(obj1 == obj2)
class A:def __init__(self):self.aa = 11self.bb = 22def __eq__(self,obj):if self.aa == obj.aa and self.bb == obj.bb:print('正在执行__eq__')
class B(A):passobj1 = A()
obj2 = B()
print(obj1 == obj2)
__new__
方法**
__new__
真正的创建并返回一个对象的方法。实例化对象时,其实首先执行的是__new__
创建内存空间
class A:def __init__(self):self.aa = 1print('创建了对象')def __new__(cls, *args, **kwargs): #第二步:执行__new__,这里测试使用,没有创建对象空间的作用ret = super().__new__(cls, *args, **kwargs) #执行一下父类的__new__创建对象使用,print('执行__new__对象')return retobj = A() #第一步,类名()
s = obj.aa
print(obj)
类名()触发__new__
并将类名自动传给cls
单例模式(设计模式)***
一个类只能实例化一个对象,无论实例化多少次,内存中都只有一个改类的对象
单例模式设计
class A:__instance = None #对象空间def __new__(cls, *args, **kwargs):if not cls.__instance : #如果没有创建过对象ret = super().__new__(cls, *args, **kwargs) #创建一个对象cls.__instance = retreturn cls.__instanceobj = A()
print(obj)
obj1 = A()
print(obj1)
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
【采用单例模式动机、原因】
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
【单例模式优缺点】
【优点】
一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
【缺点】
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用
__item__
系列
当对实例化的对象进行类似于字典的操作时,会触发__item__
系列对应的方法
class LOL:def __init__(self,name):self.name = namedef __getitem__(self, item):print(self.__dict__[item])print('在使用字典的方式查看属性时,getitem执行')def __setitem__(self, key, value):self.__dict__[key] = valueprint('在使用字典的方式添加属性时,setitem执行')def __delitem__(self, key):print('del obj[key]时,delitem执行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key时,我执行')self.__dict__.pop(item)gailun = LOL('盖伦')
gailun['age'] = 18
print(gailun.__dict__['age'])
print(gailun.age)
del gailun['age']
del gailun.age
print(gailun.__dict__['age'])
难点
class StarkConfig:def __init__(self,num):self.num = numdef run(self):self()def __call__(self, *args, **kwargs):print(self.num)class RoleConfig(StarkConfig):def __call__(self, *args, **kwargs):print(1234567)def __getitem__(self, item):return self.num[item]v1 = StarkConfig('sam')
v2 = RoleConfig('john')
v1.run()
上下文管理器相关
__enter__
__exit__
这两个方法能够把对象像文件一样进行操作
# 如果没有这两个函数时,不能进行 with as 操作
class A:def __init__(self,txt):self.txt = txtwith A('盖伦') as f1:print(f1.txt)
class LOL:def __init__(self,name):self.name = namedef __enter__(self):self.name = '召唤' + self.namereturn selfdef __exit__(self, exc_type, exc_val, exc_tb):self.name = self.name + '进行战斗'return selfwith LOL('盖伦') as f1:print(f1.name) #召唤盖伦
print(f1.name) #召唤盖伦进行战斗
应用到文件中
class Opperation:def __init__(self,name,mode):self.name = nameself.mode = modedef __enter__(self):print('这里是入口')self.file = open(self.name,self.mode)return self.filedef __exit__(self, exc_type, exc_val, exc_tb):self.file.close()print('已关闭')with Opperation('test.py','r') as f: for item in f:print(item)打开文件前显示 ---- 这里是入口
文件关闭时显示 ---- 已关闭
练习
class UserInfo:pass
class Department:passclass StarkConfig:def __init__(self,num):self.num = numdef change(self,request):print(self.num,request)def run(self):self.change(999)class RoleConfig(StarkConfig):def change(self,request):print(666,self.num)class AdminSite:def __init__(self):self._registry = {}def register(self,k,v):self._registry[k] = v(k)site = AdminSite()
site.register(UserInfo,StarkConfig)
site.register(Department,RoleConfig)for k,v in site._registry.items():v.run()
class StarkConfig:def __init__(self,num):self.num = numdef run(self):self()def __call__(self, *args, **kwargs):print(self.num)class RoleConfig(StarkConfig):def __call__(self, *args, **kwargs):print(1234567)def __getitem__(self, item):return self.num[item]v1 = StarkConfig('sam')
v2 = RoleConfig('john')
v1.run()
class A:list_display = []def get_list(self):self.list_display.insert(0,33)return self.list_display
s = A()
print(s.get_list()) # [33]
class A:list_display = [1,2,3]def __init__(self):self.list_display = []def get_list(self):self.list_display.insert(0,33)return self.list_display
s = A()
print(s.get_list()) # [33]
class A:list_display = []def get_list(self):self.list_display.insert(0,33)return self.list_display
class B(A):list_display = [11,22]s = B()
print(s.get_list()) #[33,11,22]
引用:https://www.cnblogs.com/jin-xin/articles/10325036.html
转载于:https://www.cnblogs.com/jjzz1234/p/11178724.html
python学习之面向对象(四)相关推荐
- python学习之第四课时--运算符
python学习之第四课时--运算符 运算符 1.算数运算 运算符 描述 实例 a=10,b=20 = 加,两个对象相加 a+b输出30 - 减,一个数减去另一个数 a-b输出-10 * 乘,两个数相 ...
- Python学习之面向对象编程
Python学习目录 在Mac下使用Python3 Python学习之数据类型 Python学习之函数 Python学习之高级特性 Python学习之函数式编程 Python学习之模块 Python学 ...
- python学习[第十四篇] 文件的输入与输出
python学习[第十四篇] 文件的输入与输出 标准文件类型 一般来说只要程序一执行,就会访问3个文件: 标准输入(键盘) stdin 标准输出(显示器缓冲区) stdout 默认输出到屏幕 标准错误 ...
- Python学习之面向对象高级编程
Python学习目录 1. 在Mac下使用Python3 2. Python学习之数据类型 3. Python学习之函数 4. Python学习之高级特性 5. Python学习之函数式编程 6. P ...
- Python学习笔记第四十八天(NumPy 矩阵库(Matrix))
Python学习笔记第四十八天 NumPy 矩阵库(Matrix) 转置矩阵 matlib.empty() numpy.matlib.ones() numpy.matlib.eye() numpy.m ...
- python学习(第四节课)
一.判断条件 判断符 基本使用 1<2 ,返回值为True 1>2 ,返回值为False 1==2,返回值为True 连续使用 1<2<3,返回值为True 1>-1&l ...
- Python学习之面向对象
1. 前言 上次学习了Python的基本语法,这次学面向对象,本博客主要介绍Python的面向对象和一些常用的类.本博客不太适合小白,适合有一定的编程基础的童鞋. 学习资料主要来自两处: B站Pyth ...
- 从零开始学习python编程-从0开始的Python学习014面向对象编程(推荐)
简介 到目前为止,我们的编程都是根据数据的函数和语句块来设计的,面向过程的编程.还有一种我们将数据和功能结合起来使用对象的形式,使用它里面的数据和方法这种方法叫做面向对象的编程. 类和对象是面向对象编 ...
- Python学习:面向对象基础练习——士兵突击(代码演示) 及 身份运算符
1.面向对象封装案例II--士兵突击 目标 士兵突击案例 身份运算符 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 ...
最新文章
- 基于CAP模型设计企业级真正高可用的分布式锁
- 信息互通联动防御 亚信安全翻开融合终端安全新篇章
- 走向通用智能的核心:任务树的建立
- 关于持续集成几点知识点
- 解决Matplotlib图表不能在Pycharm中显示的问题:使用Anaconda
- IntelliJ Idea取消Colud not autowire.No
- 编写一个爬虫类库——(一)想法
- Python实现模板
- android -------- java虚拟机和Dalvik虚拟机
- 可用于wpf的图表控件:WPFTookit Chart
- EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY‘RE NOT. RENEWALS ARE LESSER
- html+css+js实现的3D魔方小游戏源代码
- IFC标准是什么标准?IFC标准的发展历程是怎样的?
- 将PDF论文的公式截图后转成Word可编辑公式
- 大麦网抢票python代码_damai_ticket
- 单片机c语言条件语句,单片机c语言教程:C51复合语句和条件语句
- Kafka 的七年之痒
- python简单爬虫入库_python用BeautifulSoup库简单爬虫实例分析
- 第十四届蓝桥杯模拟赛【第三期】Python
- FLStudio水果21最新Daw (宿主软件)电音混音编曲制作工具