一 、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面向对象进阶(上)的更多相关文章

  1. Python面向对象进阶(二)

    Python面向对象进阶2.html :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1 ...

  2. Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)

    Python开发[第七篇]:面向对象   详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇)   上一篇<Python 面向对象(初级篇)> ...

  3. Python面向对象进阶和socket网络编程-day08

    写在前面 上课第八天,打卡: 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __i ...

  4. Python面向对象进阶和socket网络编程

    写在前面 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __init__(self ...

  5. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  6. python面向对象进阶

    前言 上节大话python面向对象对面向对象有了一些了解,这次就不用大话风格了 (ps:真心不好扯啊) isinstance与issubclass isinstance(obj,cls)检查是否obj ...

  7. python 面向对象进阶之内置方法

    一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...

  8. Python 面向对象 (进阶篇)

    <Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可 ...

  9. Python之路-python(面向对象进阶)

    一.面向对象高级语法部分 1.静态方法.类方法.属性方法 2.类的特殊方法 3.反射 二.异常处理 三.Socket开发基础 一.面向对象高级语法部分 静态方法(@staticmethod) 定义:只 ...

随机推荐

  1. 谷歌js编码规范解析

    http://alloyteam.github.io/JX/doc/specification/google-javascript.xm 阅读了谷歌js编码规范,我发现了很多,js的里面很多要注意的问 ...

  2. VMware快照

    越来越多的人喜欢使用虚拟机来做实验,但是实验过程并不总是顺利的,所以我们就需要掌握虚拟机快照的使用方法,个人建议的顺序为: 1 在虚拟机打开之前,点击“虚拟机”--"快照"--&q ...

  3. Visual Studio 2013安装包

    点击下载

  4. LeetCode 215——数组中的第 K 个最大元素

    1. 题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 ...

  5. 基于规则的中文分词 - NLP中文篇

    之前在其他博客文章有提到如何对英文进行分词,也说后续会增加解释我们中文是如何分词的,我们都知道英文或者其他国家或者地区一些语言文字是词与词之间有空格(分隔符),这样子分词处理起来其实是要相对容易很多, ...

  6. eclipse 创建Makefile工程生成多个执行文件

    1.创建Makefile工程 2.创建inc src Debug 目录 用于存放头文件源文件 3.编写Makefile 需要在有源文件的目标天剑Makefile文件,如下给出一个生成两个target的 ...

  7. 官方文档 恢复备份指南八 RMAN Backup Concepts

    本章内容 Consistent and Inconsistent RMAN Backups Online Backups and Backup Mode Backup Sets Image Copie ...

  8. [译]在Python中如何使用额enumerate 和 zip 来迭代两个列表和它们的index?

    enumerate - 迭代一个列表的index和item <Python Cookbook>(Recipe 4.4)描述了如何使用enumerate迭代item和index. 例子如下: ...

  9. 软工实践 - 第二十九次作业 Beta 冲刺(7/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10159251.html 作业博客:[班级博客本次作业的链接] (https://edu.cnb ...

  10. vue2.0中vue-router使用总结

    #在vue-cli所创建的项目中使用 进入到项目的目录后使用  npm install vue-router --save  安装vue-router,同时保存在webpack.Json配置文件中,然 ...