python面向对象进阶(上)
一 、isinstance(obj,cls)和issubclass(sub,super)
(1)isinstance(obj,cls)检查对象obj是否是类 cls 的对象,返回True和Flase
示例:
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
p=People("xuyaunyuan")
print(p.name)
print(isinstance(p,People))#判断对象P是不是类People的对象
执行结果是:
xuyaunyuan
True
(2)issubclass(sub, super)检查sub类是否是 super 类的派生类,返回True和Flase
示例:
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
class Student(People):
def __init__(self,name,id):
self.name=name
self.id=id
print(issubclass(Student,People))#检查Student类是否是 super 类(people类)的派生类
执行结果是:
True
二 、反射
(1)反射的概念:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
(2)四个可以实现自省的函数(下列方法适用于类和对象,一切皆对象,类本身也是一个对象)
a、hasattr(object,name)——判断object中有没有一个name字符串对应的方法或属性
b、getattr(object,name)——获取属性
c、setattr(x, y, v)——设置属性
d、delattr(x, y)—— 删除属性
分别示例:
a、hasattr(object,name)——判断object中有没有一个name字符串对应的方法或属性
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
p=People("xuyaunyuan")
#hasattr有没有
print(hasattr(p,"name"))#判断对象P有没有name属性
print("name" in p.__dict__)#等同于上面
执行结果是:
True
True
b、getattr(object, name, default=None)——获取属性
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
p=People("xuyaunyuan")
#getattr#获取
print(getattr(p,"country"))#获取数据属性country
print(getattr(p,"name"))
执行结果是:
china
xuyaunyuan
c、setattr(x, y, v)——设置属性
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
p=People("xuyaunyuan")
#setattr设置setatttr(x指对象,y指属性,v指value值)
setattr(p,"age",18)
setattr(p,"sex","woman")
print(p.__dict__)#查看是否设置成功
执行结果是:
{'name': 'xuyaunyuan', 'age': 18, 'sex': 'woman'}
d、delattr(x, y)—— 删除属性
class People:
country="china"
def __init__(self,name):
self.name=name
def test(self):
print("test")
p=People("xuyaunyuan")
#delattr#删除
delattr (p,"name")
print(p.__dict__)#查看是否删除成功
执行结果是:
{}
总结:
hasattr(obj,'属性') #obj.属性 是否存在
getattr(obj,'属性') #获取obj.属性 不存在则报错
getattr(obj,'属性','默认值') #获取obj.属性 不存在不会报错,返回那个默认值
setattr(obj,'属性','属性的值') #obj.属性=属性的值
delattr(obj,'属性') #del obj.属性
(3)反射当前模块的属性
关于文件的2种运行方式:把文件当脚本运行和把文件当做模块导入
a、关于导入其他模块,利用反射查找该模块是否存在某个方法
示例:
新建2个文件,分别取名为test.py和test1.py
import sys
##在test.py文件下定义一些名字
x=11#定义变量名x
class People:#定义类名People
def __init__(self):
pass
def s1():#定义函数名s1
print("s1")
def s2():#定义函数名s2
print("s2")
import test#在test1.py的文件下导入test模块 #在test1.py的文件下导入test模块
print(test)#打印导入的test模块
print(test.People)#打印类
test.s1()#运行函数s1
test.s2()#运行函数s2
print(test.x)#打印变量x
执行结果是:
<module 'test' from 'C:\\Users\\Administrator\\PycharmProjects\\py_fullstack_s4\\day32-面向对象进阶\\模块导入\\test.py'>
<class 'test.People'>
s1
s2
11
b、在自己的文件内部查看自己的模块
this_module = sys.modules[__name__]#在自己的文件内查看自己的模块和绝对路径
print(this_module)
示例:
import sys
class Foo:
pass
def s1():
print('s1') def s2():
print('s2')
this_module = sys.modules[__name__]#在自己的文件内查看自己的模块和绝对路径
print(this_module) print(hasattr(this_module, 's1'))#也可进行判断在this_module里面有没有s1
print(getattr(this_module, 's2'))#也可获取this_module里面的s2
this_module.s2()#运行s2函数
this_module.s1()#运行s1函数
执行结果是:
<module '__main__' from 'E:/飞秋/徐圆圆课程视频/Python fullstack s4 基础篇-day31/day31/test.py'>
True
<function s2 at 0x000000000282A8C8>
s2
s1
(4)反射的好处(为什么要用反射)
好处一:实现可插拔机制
反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
示例:
新建2个文件,分别为客户端和服务端
在客户端定义如下:
class FtpClient:
'ftp客户端,但是还有没有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr
def test(self):
print('test')
在服务端调用:
import ftpclient
print(ftpclient)
f1=ftpclient.FtpClient('192.168.1.1')
if hasattr(f1,'get'):#客户端并没有定义get函数,如果定义了的话,即可运行
func=getattr(f1,'get')#客户端并没有定义get函数
func()
else:
print('其他逻辑')
执行结果是:
<module 'ftpclient' from 'E:\\飞秋\\徐圆圆课程视频\\Python fullstack s4 基础篇-day31\\day31\\反射实现可插拔机制\\ftpclient.py'>
正在连接服务器[192.168.1.1]
其他逻辑
好处二:动态导入模块
示例:方法一 (利用内置函数)
#不推荐用法
m=input("请输入你要导入的模块:")
m1=__import__(m)#内置函数
print(m1)
print(m1.time())
执行结果是:
请输入你要导入的模块:time
<module 'time' (built-in)>
1493024366.8544436
示例:方法二(推荐用法)
#推荐使用方法
import importlib#调用模块
t=importlib.import_module('time')
print(t.time())
执行结果是:
1493024403.4785383
三、__setattr__,__delattr__,__getattr__
三个参数,给对象添加属性
__setattr__ 添加/修改属性会触发它的执行
__delattr__ 删除属性的时候会触发
__getattr__ 只有在使用点调用属性且属性不存在的时候才会触发
作用:系统内置函数属性(你定义了就用你定义的函数属性,不定义就用系统默认的函数属性)
整体使用情况示例:
class Foo:
def __init__(self,name):
self.name=name
def __setattr__(self, key, value):
print("——setattr——key:%s value:%s"%(key,value))
print(type(key))
print(type(value))
# self.key = value # 这就无限递归了,不能用
self.__dict__[key]=value#将值加入字典内 def __delattr__(self, item):
print("——delattr——item:%s"%item)
print(type(item))
# del self.item #无限递归了,不能用
self.__dict__.pop(item)#删除 def __getattr__(self, item):
print('----> from getattr:你找的属性不存在') #__setattr__添加/修改属性会触发它的执行
f=Foo("xuyuanyuan")
print(f.__dict__)# 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f.age="18"#增加age属性
print(f.__dict__) #__delattr__删除属性的时候会触发
f.__dict__['age']=18#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f.age
print(f.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f.aaa
执行结果:
——setattr——key:name value:xuyuanyuan
<class 'str'>
<class 'str'>
{'name': 'xuyuanyuan'}
——setattr——key:age value:18
<class 'str'>
<class 'str'>
{'name': 'xuyuanyuan', 'age': '18'}
——delattr——item:age
<class 'str'>
{'name': 'xuyuanyuan'}
----> from getattr:你找的属性不存在
总结:
obj点的方式去操作属性时触发的方法
__getattr__:obj.属性 不存在时触发
__setattr__:obj.属性=属性的值 时触发
__delattr__:del obj.属性 时触发
四 、二次加工标准类型(包装)
示例,如果是用继承的方法实现二次加工
# #基于继承的原理,来定制自己的数据类型(继承标准类型)
# 定制自己的append:只能向列表加入字符串类型的值
class List(list):
def append(self,p_obiect):
if not isinstance(p_obiect,str):#判断加入的是否是字符串的,如果不是字符串的话,则会报错
raise TypeError("must be str")#报错,提示必须是字符串
else:
super().append(p_obiect)#将加入的字符串加入到超父类list内 l=List([1,2,3,4])
l.append("hello")
print(l)
执行结果是:
[1, 2, 3, 4, 'hello']
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
1、通过触发__getattr__方法
示例:
# 定制显示列表中间那个值的属性
class List:
def __init__(self,list=[1,2,3,4]):
self.list=list
def append(self, p_obiect):
if not isinstance(p_obiect, int): # 判断加入的是否是字符串的,如果不是字符串的话,则会报错
raise TypeError("must be int") # 报错,提示必须是字符串
else:
self.list.append(p_obiect) # 将加入的字符串加入到超父类list内
@property#装饰器功能,search=property(search)相当于调用了property函数
def search(self):
print(self.list[len(self.list)//2],type(self.list[len(self.list)//2]))
def __getattr__(self, item):#属性不存在时则会触发运行
print("你找的属性不存在") l=List()
print(l.list)
l.append(5)
print(l.list)
# 没加@property的话,则需要c.search()调用
# 加了@property装饰器的话,可直接当做属性调用c.search
l.search#可直接当做属性调用
# print(f.read())
l.pop#当调用没有的属性时,则会触发__getattr__的运行
执行结果是:
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
3 <class 'int'>
你找的属性不存在
python面向对象进阶(上)的更多相关文章
- Python面向对象进阶(二)
Python面向对象进阶2.html :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1 ...
- Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)
Python开发[第七篇]:面向对象 详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇) 上一篇<Python 面向对象(初级篇)> ...
- Python面向对象进阶和socket网络编程-day08
写在前面 上课第八天,打卡: 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __i ...
- Python面向对象进阶和socket网络编程
写在前面 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __init__(self ...
- python面向对象进阶(八)
上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...
- python面向对象进阶
前言 上节大话python面向对象对面向对象有了一些了解,这次就不用大话风格了 (ps:真心不好扯啊) isinstance与issubclass isinstance(obj,cls)检查是否obj ...
- python 面向对象进阶之内置方法
一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...
- Python 面向对象 (进阶篇)
<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可 ...
- Python之路-python(面向对象进阶)
一.面向对象高级语法部分 1.静态方法.类方法.属性方法 2.类的特殊方法 3.反射 二.异常处理 三.Socket开发基础 一.面向对象高级语法部分 静态方法(@staticmethod) 定义:只 ...
随机推荐
- No resources found. Error from server (NotAcceptable): unknown (get pods)
问题:正确安装kubectl后,可查询到当前使用集群服务,也可切换不同的集群,但无法获取当前运行的pods的信息与所有的service,具体表现为 $ kubectl get po -nwx No r ...
- lua敏感词过滤
--过滤敏感词(如果onlyKnowHas为true,表示只想知道是否存在敏感词,不会返回过滤后的敏感词,比如用户注册的时候,我们程序是只想知道用户取的姓名是否包含敏感词的(这样也能提高效率,检测到有 ...
- (原创)白话KMP算法(续)
第二章:KMP改良算法 第一章里面我们讲完了KMP算法的next数组实现法,回忆一下其实最重要的内容无非就是一.理解 i 指针无用回溯的意义,二.理解 j 指针的定位和模式串中每个元素重复度的关系,三 ...
- EM算法浅析(一)-问题引出
EM算法浅析,我准备写一个系列的文章: EM算法浅析(一)-问题引出 EM算法浅析(二)-算法初探 一.基本认识 EM(Expectation Maximization Algorithm)算法即期望 ...
- 容器基础(七): 使用docker compose部署程序
配置 在上一节的基础上, 增加如下的docker-compose.yml文件, 然后用docker-compose up命令启动容器进行部署: version: " services: s ...
- 福大软工1816:Alpha(3/10)
Alpha 冲刺 (3/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1.学习qqbot库: 2.实 ...
- lintcode-49-字符大小写排序
49-字符大小写排序 给定一个只包含字母的字符串,按照先小写字母后大写字母的顺序进行排序. 注意事项 小写字母或者大写字母他们之间不一定要保持在原始字符串中的相对位置. 样例 给出"abAc ...
- Activiti工作流(一)——Activiti Diagram
工作流解决在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现. 使用Eclipse开发,需要安排工作流插件,详情见下面. Name ...
- 算法(7)Majority Element II
题目:找出数组中出现次数大于n/3次的数字 思路:摩尔投票法.所有的帖子中都说:先遍历一遍数组找到备选元素,然后再遍历一遍数组考察下这个元素是否是真的超过n/3,然后就直接上代码,但是现在的问题是:我 ...
- [剑指Offer] 9.变态跳台阶
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. [思路1]每个台阶都有跳与不跳两种可能性(最后一个台阶除外),最后一个台阶必 ...