一、isinstance(obj,cls)和issubclass(sub,super)

  1、isinstance(obj,cls)检查obj是否是类 cls 的对象

class A:
pass obj = A() #实例化对象obj
isinstance(对象名,类名)#语法
print(isinstance(obj,A)) #isinstance函数返回的是布尔值,True,则obj,是A产生的对象
print(isinstance(object,A)) #同上,反之,为不是。
---------------输出结果-------------------
True
False

  2、issubclass(sub, super)检查sub类是否是 super 类的派生类或子类

class A: #定义父类
pass class B(A): #定义子类,继承A
pass issubclass(子类名,父类名) #语法
print(issubclass(B,A)) #返回的也是布尔值,True为真,则B,是A的子类,反之,不是
-------------输出结果------------------
True

  二、反射

  1、什么是反射:

  反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自

省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp

和面向对象方面取得了成绩。  

  2、反射的简单含义:

    1、通过类名获得类的实例对象

    2、通过方法名得到方法,实现调用

  3、python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用

反射)。

  反射即想到4个内置函数分别为:hasattr、getattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员下面

逐一介绍先看例子:

class motorcycle: #仅限二轮摩托
feature = "两个轱辘" #相对而言
def __init__(self,brand,price):
self.brand = brand
self.price = price
def advance(self): #都有前进的技能
print("%s,出发了!"%self.brand)
def stop(self): #都有减速,停车功能
print("%s,减速了!"%self.brand) m1 = motorcycle("春风",28800) #实例化对象m1

  3.1、hasattr(obj,"name"):检测obj里是否含有"name"属性

#检测是否含有某属性
print(hasattr(m1,"feature")) #检测对象m1是否有类的数据属性
print(hasattr(m1,"brand")) #检测m1里是否有"brand"这个数据属性
print(hasattr(m1,"advance")) #检测m1里是否有"advance"这个绑定方法
print(hasattr(motorcycle,"feature")) #一切皆对象,加测类里面是否有"feature"这个数据属性
print(hasattr(motorcycle,"stop")) #一切皆对象,检测类里面是否有"stop"这个函数属性
print(hasattr(m1,"abcd")) #检测到没有这个"abcd"的时候,此时,会返回False
----------------------输出结果-------------------
True
True
True
True
True
False

  3.2、getattr(obj,"name"):获取obj里的"name"的属性

#获取某属性
n = getattr(m1,"brand") #获取m1的品牌属性,并赋值给n
print(n) #打印n
n1 = getattr(motorcycle,"feature") #一切皆对象,获取类的数据属性,并赋值给n1
print(n1) #打印n1
n2 = getattr(m1,"feature") #获取对象m1的类的特征,并赋值给n2
print(n2) #打印n2
n3 = getattr(m1,"advance") #获取m1的绑定方法,并赋值给n3
n3() #现在n3就是m1的绑定方法,加括号就能调用
n4 = getattr(motorcycle,"stop") #获取类的函数属性,并赋值给n4
n4(m1) #因为n4是类的函数属性,so,调用的时候要传参
#getattr(m1,"abcd") #没有abcd"会报错
print(getattr(m1,"abcd","不存在啊!")) #没有"abcd"会打印后面的字符串
-----------------输出结果--------------------
春风
两个轱辘
两个轱辘
春风,出发了!
春风,减速了!
不存在啊!

  3.3、setattr(obj,"name",content):设置obj里的"name"的属性

#设置某属性
setattr(m1,"displacement",650) #新增m1的"displacement"数据属性
setattr(m1,"show_brand",lambda self: self.brand+"666") #新增m1的函数属性
setattr(m1,"price",26800) #春风做活动,回馈车友,减价2000,修改m1的价格
setattr(motorcycle,"show_brand",lambda self:self.brand+"666") #新增类的函数属性
setattr(motorcycle,"feature","两个轱辘,还有三个轱辘的") #修改类的特征
print(m1.show_brand(m1)) #注意,此时"show_brand"就是一个普通函数,需要传一个参数进去
print(motorcycle.show_brand(m1)) #类名.新增的函数名加括号调用,因为是函数属性,so,要传参
print(m1.__dict__) #打印对象m1的所有的属性
print(motorcycle.__dict__) #打印类motorcycle的所有的属性
-------------------输出结果--------------------------
春风666
春风666
{'brand': '春风', 'price': 26800, 'displacement': 650, 'show_brand':\
<function <lambda> at 0x0000000002113E18>}
{'__module__': '__main__', 'feature': '两个轱辘,还有三个轱辘的',\
'__init__': <function motorcycle.__init__ at 0x00000000025FA950>,\
'advance': <function motorcycle.advance at 0x00000000025FA9D8>,\
'stop': <function motorcycle.stop at 0x00000000025FAA60>, '__dict__': \
<attribute '__dict__' of 'motorcycle' objects>, '__weakref__': <attribute \
'__weakref__' of 'motorcycle' objects>, '__doc__': None, 'show_brand': \
<function <lambda> at 0x00000000025FAAE8>}

  3.4、delattr(obj,"name"):删除obj里的"name"的属性

#删除某属性
delattr(m1,"displacement") #删除m1的"displacement"数据属性
delattr(m1,"show_brand") #删除m1的"show_brand"的函数属性
delattr(motorcycle,"show_brand") #删除类的函数属性
print(m1.__dict__) #打印对象m1的所有的属性
print(motorcycle.__dict__) #打印类motorcycle的所有的属性
--------------------输出结果-------------------------
{'brand': '春风', 'price': 28800}
{'__module__': '__main__', 'feature': '两个轱辘', '__init__': \
<function motorcycle.__init__ at 0x000000000291A950>,\
'advance': <function motorcycle.advance at 0x000000000291A9D8>, \
'stop': <function motorcycle.stop at 0x000000000291AA60>,\
'__dict__': <attribute '__dict__' of 'motorcycle' objects>,\
'__weakref__': <attribute '__weakref__' of 'motorcycle' objects>,\
'__doc__': None}

  4、为什么用反射之反射的好处

  好处一:实现可插拔机制

  可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思

?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能。

#类代码同上
if hasattr(m1,"advance"): #判断m1里是否含有"advance"属性,有就执行里面的代码
func = getattr(m1,"advance") #有就实现此行代码,这样就不会出现异常,将获取到的内存地址给func
func() #调用次方法
print("继续其他逻辑") #就算没有也不会影响下面代码的执行,实现了可插拔机制
--------------------输出结果---------------------
春风,出发了!
继续其他逻辑

  好处二:动态导入模块(基于反射当前模块成员)

#模块(mokuai)的内容:
x = 123 #变量x
class A: #定义一个类
def aaa(self): #类A的函数属性aaa
print("from aaa")
def bbb(): #定义一个函数bbb
print("from bbb")

  动态导入模块:

import  importlib
this_module = importlib.import_module("mokuai")
#语法就是this_module.属性名
print(this_module.x) #打印模块里变量x的值,
a = this_module.A() #类A实例化对象a
a.aaa() #对象a调用绑定方法
this_module.bbb() #调用函数bbb
----------------输出结果--------------------
123
from aaa
from bbb

  三、__setattr__,__getattr__,__delattr__

class foo:
def __init__(self,name):
self.name = name
def __setattr__(self, key, value): #添加/修改属性时,会触发它的执行
if not isinstance(value,str):
raise TypeError("must be str")
#self.key = value #注意:这样就无限递归了
self.__dict__[key] = value
def __getattr__(self, item): #当属性不存在的时候,会触发它的执行
print("不存在----->%s"%item)
def __delattr__(self, item): #删除属性时,会触发它的执行
# print("不能被删除!") #强制不让删除
#del self.item #注意:这样就无限递归了
self.__dict__.pop(item) #真正删除的方法 f1 = foo("michael") # 实例化对象f1
#调用__setattr__
print(f1.__dict__) #打印f1的属性字典
f1.age = "18" #"18"必须是str,赋值就会触发__setattr__的执行
print(f1.__dict__) #打印f1的属性字典 #调用__getattr__
print(f1.abcd) #此时abcd是不存在的,没有这个属性,会返回None #调用__delattr__
del f1.age #删除属性
print(f1.__dict__) #打印f1的属性字典
-------------------输出结果-----------------------
{'name': 'michael'}
{'name': 'michael', 'age': '18'}
不存在----->abcd
None
{'name': 'michael'}

  四、二次加工标准类型(包装)

  包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型

来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的

方式进行二次加工)。

#基于继承的原理,来定制自己的数据类型(继承标准类型)
class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和insert
def append(self, p_object): #自己加工追加的方法
if not isinstance(p_object,int): #加上条件,不是int就抛出异常
raise TypeError("must be int") #返回提示输入类型
#self.append(p_object) #注意:这样就无限递归了
super().append(p_object) #此时才会完成追加 def insert(self, index, p_object): #自己加工指定位置插入的方法
if not isinstance(p_object,int): #加上条件,不是int就抛出异常
raise TypeError("must be int") #返回提示输入类型
super().insert(index,p_object) #此时才会完成插入 l1 = List([0,1,2]) #实例化对象l1
print(l1) #打印列表l1
l1.append(3) #对象l1追加元素3,注意必须是int
print(l1) #打印列表l1
# l1.append("5") #此时会抛出异常,"5"不是int
l1.insert(0,-1) #在下标0的位置,插入元素-1,注意元素的类型
l1.insert(5,4) #在下标5的位置,插入元素4,注意元素的类型
print(l1) #打印列表l1
print(l1.index(4)) #获取元素的下标,没有派生出自己的方法的时候,会继承父类的方法
--------------------输出结果------------------------
[0, 1, 2]
[0, 1, 2, 3]
[-1, 0, 1, 2, 3, 4]
5

  授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有

产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给

对象的默认属性。

  实现授权的关键点就是覆盖__getattr__方法。

import time
class Open: #open是一个函数,不是类,不能用继承,so,用另一种方式:授权
def __init__(self,file_path,m="r",endoce="utf8"):
self.file = open(file_path,mode=m,encoding=endoce) #获取文件句柄
self.file_path = file_path #文件路径
self.mode = m #文件打开模式
self.encoding = endoce #文件的编码方式 def write(self,line): #写入文件
t = time.strftime("%Y-%m-%d %X") #获取时间格式
self.file.write("%s ---> %s"%(t,line)) #前面加上时间,按格式写入
def __getattr__(self, item): #当方法不存在的时候,会触发它的执行
return getattr(self.file,item) #获取文件其他的方法,并返回给对象 f1 = Open("a.txt","w") #实例化对象f1,创建文件a.txt,以w模式
f1.write("1、你好,我摩旅去了!\n") #按自己加工的方法写入内容
f1.write("2、你好,我摩旅去了!\n") #按自己加工的方法写入内容
f1.write("3、你好,我摩旅去了!\n") #按自己加工的方法写入内容
f1.close() #关闭文件
f2 = Open("a.txt","r") #实例化对象f2,查看文件a.txt,以r模式
print(f2.read()) #打印输出a.txt的文件内容
f2.seek(0) #刚看完,光标走到最后位置了。要想再看,就得把光标调到最开始位置
print("-->:",f2.read()) #加上标识,再看一遍
f2.close() #关闭文件
-----------------输出结果------------------
2017-04-24 18:30:57 ---> 1、你好,我摩旅去了!
2017-04-24 18:30:57 ---> 2、你好,我摩旅去了!
2017-04-24 18:30:57 ---> 3、你好,我摩旅去了! -->: 2017-04-24 18:30:57 ---> 1、你好,我摩旅去了!
2017-04-24 18:30:57 ---> 2、你好,我摩旅去了!
2017-04-24 18:30:57 ---> 3、你好,我摩旅去了!

  授权小练习:

#要求:
# 基于授权定制自己的列表类型,要求定制的自己的__init__方法,
# 定制自己的append:只能向列表加入字符串类型的值
# 定制显示列表中间那个值的属性(提示:property)
# 其余方法都使用list默认的(提示:__getattr__加反射) class list: #定义一个类list
def __init__(self,li):
self.li = li
def append(self,value): #自己加工追加的方法
if not isinstance(value,str): #加上条件,不是str就抛出异常
raise TypeError("must be str") #返回提示输入类型
self.li.append(value) #追加到列表中
@property
def pro(self): #加上装饰器的pro,获取属性
index = len(self.li)//2 #获取列表中间的索引
return self.li[index] #返回中间的元素 def __getattr__(self, item): #当方法不存在的时候,会触发它的执行
return getattr(self.li,item) #获取列表其他的方法,并返回给对象 l1 = list([1,2,3]) #实例化对象l1,新建列表
print(l1.li) #查看列表的内容
# l1.append(4) #此时会抛出异常,因为不是str类型
l1.append("4") #往l1列表追加内容
print(l1.li) #打印追加后的列表
print(l1.pro) #pro加property后,调用不用加括号了,跟获取数据属性一样
print(l1.index(2)) #自己没有定义的方法,会触发__getattr__,使用list其\
他的方法,这里查看元素2的索引是多少
---------------------输出结果---------------------
[1, 2, 3]
[1, 2, 3, '4']
3
1

  

Python基础之面向对象进阶一的更多相关文章

  1. 周末班:Python基础之面向对象进阶

    面向对象进阶 类型判断 issubclass 首先,我们先看issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类. class Base: pass class Foo(Base ...

  2. python基础_面向对象进阶

    @property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我 ...

  3. Python之路【第六篇】python基础 之面向对象进阶

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

  4. 学习PYTHON之路, DAY 8 - PYTHON 基础 8 (面向对象进阶)

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  5. Python基础之面向对象进阶二

    一.__getattribute__ 我们一看见getattribute,就想起来前面学的getattr,好了,我们先回顾一下getattr的用法吧! class foo: def __init__( ...

  6. 自学Python之路-Python基础+模块+面向对象+函数

    自学Python之路-Python基础+模块+面向对象+函数 自学Python之路[第一回]:初识Python    1.1 自学Python1.1-简介    1.2 自学Python1.2-环境的 ...

  7. Python 基础 四 面向对象杂谈

    Python 基础  四  面向对象杂谈 一.isinstance(obj,cls) 与issubcalss(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls ...

  8. 二十. Python基础(20)--面向对象的基础

    二十. Python基础(20)--面向对象的基础 1 ● 类/对象/实例化 类:具有相同属性.和方法的一类人/事/物 对象(实例): 具体的某一个人/事/物 实例化: 用类创建对象的过程→类名(参数 ...

  9. 十三. Python基础(13)--生成器进阶

    十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...

随机推荐

  1. Java基础_0309:this关键字

    this简介 在Java中this可以完成三件事情:表示本类属性.表示本类方法.当前对象(只是先介绍概念) 调用本类属性 在一个类中定义的方法中可以直接访问类中的属性,但是很多时候有可能会出现方法参数 ...

  2. 源码解读-文件上传angularFileUpload1

    angular-file-upload 1.文件上传模块的引入就不赘述,简单准备 2.初始化组件并绑定change事件 3.监听用户选择文件FileItem(change事件),push进文件数组qu ...

  3. link标签和css引入方式

    link常见用途 <link> 标签最常见的用途是链接样式表,在 HTML 中,<link> 标签没有结束标签,此元素只能存在于 head 部分,不过它可出现任何次数. < ...

  4. Python 爬虫六 性能相关

    前面已经讲过了爬虫的两大基础模块: requests模块:用来伪造请求爬取数据 bs4模块:用来整理,提取数据 当我们真正的开始有需求的时候通常都是批量爬取url这样的.那如何批量爬取呢? 按照正常的 ...

  5. 转:Java项目开发规范参考

    Java项目开发规范参考 - KevinLee的博客 - 博客频道 - CSDN.NEThttp://blog.csdn.net/u011383131/article/details/51227860 ...

  6. 给出随机存储器(RAM)和只读存储器(ROM)的差别

    给出随机存储器(RAM)和只读存储器(ROM)的差别

  7. linux系统 之 git

    1,git是啥? 最流行的分布式版本控制系统,在高度易用的同时,仍然保留着初期设定的目标.它的速度飞快,极其适合管理大项目,它还有着令人难以置信的非线性分支管理系统,可以应付各种复杂的项目开发需求. ...

  8. C中的malloc/free与C++中的new/delete的用法与区别

    1.先介绍malloc/free的用法: 原型函数: void *malloc(long NumBytes); 该函数分配了NumBytes个字节的内容,分配的空间是堆空间 malloc()根据用户所 ...

  9. openstack Q版部署-----界面horizon安装(9)

    一.界面的安装 控制节点安装软件包: yum install openstack-dashboard -y [root@linux-node1 ~]# vim /etc/openstack-dashb ...

  10. $resource详解

    $resource 首先添加$resource的引用 <script src="Scripts/angular.min.js"></script> < ...