Python之面向对象反射

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

1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)

  issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo(object):
pass class Bar(Foo):
pass issubclass(Bar, Foo)

  反射:

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

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

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性
 def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass

getattr(object, name, default=None)

 def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass

setattr(x, y, v)

 def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
"""
pass

delattr(x, y)

 class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name) b1=BlackMedium('万成置地','回龙观天露园') #检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house')) #获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func() # getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊')) #设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1)) #删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错 print(b1.__dict__)

四个方法的使用演示

 class Foo(object):

     staticField = "old boy"

     def __init__(self):
self.name = 'wupeiqi' def func(self):
return 'func' @staticmethod
def bar():
return 'bar' print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')

类也是对象

 #!/usr/bin/env python
# -*- coding:utf-8 -*- import sys def s1():
print 's1' def s2():
print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1')
getattr(this_module, 's2')

反射当前模块成员

导入其他模块,利用反射查找该模块是否存在某个方法

 #!/usr/bin/env python
# -*- coding:utf-8 -*- def test():
print('from the test')

module_test.py

 #!/usr/bin/env python
# -*- coding:utf-8 -*- """
程序目录:
module_test.py
index.py 当前文件:
index.py
""" import module_test as obj #obj.test() print(hasattr(obj,'test')) getattr(obj,'test')()
 class People:
country='China'
def __init__(self,name):
self.name=name
# def walk(self):
# print('%s is walking' %self.name)
p=People('egon')
#
# People.country
# print(People.__dict__) # print(p.name)
# print(p.__dict__) # p.name #hasattr
# print('name' in p.__dict__)
# print(hasattr(p,'name'))
# print(hasattr(p,'name1213')) # print(hasattr(p,'country')) #p.country
# print(hasattr(People,'country')) #People.country
# print(hasattr(People,'__init__')) #People.__init__ #getattr
# res=getattr(p,'country') #res=p.country
# print(res)
#
# f=getattr(p,'walk') #t=p.walk
# print(f)
#
# f1=getattr(People,'walk')
# print(f1)
#
# f()
# f1(p) # print(p.xxxxxxx)
# print(getattr(p,'xxxxxxxx','这个属性确实不存在')) #
# if hasattr(p,'walk'):
# func=getattr(p,'walk')
# func()
#
# print('================>')
# print('================>') #setattr # p.sex='male'
# print(p.sex)
# print(p.__dict__) # setattr(p,'age',18)
# print(p.__dict__)
# print(p.age)
# print(getattr(p,'age')) #delattr
# print(p.__dict__)
# del p.name
# print(p.__dict__) print(p.__dict__)
delattr(p,'name')
print(p.__dict__)

3 为什么用反射之反射的好处

好处一:实现可插拔机制

有俩程序员,一个lili,一个是egon,lili在写程序的时候需要用到egon所写的类,但是egon去跟女朋友度蜜月去了,还没有完成他写的类,lili想到了反射,使用了反射机制lili可以继续完成自己的代码,等egon度蜜月回来后再继续完成类的定义并且去实现lili想要的功能。

总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能

 class FtpClient:
'ftp客户端,但是还么有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr

还没有实现全部功能

 #from module import FtpClient
f1=FtpClient('192.168.1.1')
if hasattr(f1,'get'):
func_get=getattr(f1,'get')
func_get()
else:
print('---->不存在此方法')
print('处理其他的逻辑')

不影响lili的代码编写

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

  反射的用途:

    

import sys
def add():
print('add') def change():
print('change') def search():
print('search') def delete():
print('delete') this_module=sys.modules[__name__]
while True:
cmd=input('>>:').strip()
if not cmd:continue
if hasattr(this_module,cmd):
func=getattr(this_module,cmd)
func()
# if cmd in func_dic: #hasattr()
# func=func_dic.get(cmd) #func=getattr()
# func() # func_dic={
# 'add':add,
# 'change':change,
# 'search':search,
# 'delete':delete
# } # while True:
# cmd=input('>>:').strip()
# if not cmd:continue
# if cmd in func_dic: #hasattr()
# func=func_dic.get(cmd) #func=getattr()
# func() # class Foo:
# x=1
# def __init__(self,name):
# self.name=name # def walk(self):
# print('walking......')
# f=Foo('egon') # Foo.__dict__={'x':1,'walk':....}
# 'x' in Foo.__dict__ #hasattr(Foo,'x')
# Foo.__dict__['x'] #getattr(Foo,'x')
# print(Foo.x) #'x' in Foo.__dict__

  反射实现可插拔机制:

    FTP Server:

 import ftpclient
#
# print(ftpclient)
# print(ftpclient.FtpClient)
# obj=ftpclient.FtpClient('192.168.1.3')
#
# print(obj)
# obj.test() #
f1=ftpclient.FtpClient('192.168.1.1')
if hasattr(f1,'get'):
func=getattr(f1,'get')
func()
else:
print('其他逻辑')

    FTP Client:

 class FtpClient:
'ftp客户端,但是还么有实现具体的功能'
def __init__(self,addr):
print('正在连接服务器[%s]' %addr)
self.addr=addr
def test(self):
print('test') def get(self):
print('get------->')

  通过字符串导入模块:

# m=input("请输入你要导入的模块:")

# m1=__import__(m)  #官方不推荐
# print(m1)      #官方不推荐
# print(m1.time())  #官方不推荐 #官方推荐使用方法
import importlib
t=importlib.import_module('time')
print(t.time())

  attr系列:

  __getattr__、__setattr__、__delattr__

  setattr:为对象设置属性的时候回触发setattr的运行。

 getattr:只有在使用点调用属性且属性不存在的时候才会触发
 class Foo:
x=1
def __init__(self,y):
self.y=y def __getattr__(self, item):
print('----> from getattr:你找的属性不存在') def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它 def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item) #__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__) #__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__) #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

三者的用法演示

  定制自己的数据类型:    

# l=list([1,2,3])
#
# l.append(4)
# l.append('5')
# print(l) # class List(list):
# pass
#
# l1=List([1,2,3])
# print(l1)
# l1.append(4)
# print(l1)
# l1.append('5')
# print(l1) #基于继承的原理,来定制自己的数据类型(继承标准类型) # class List(list):
# def append(self, p_object):
# # print('--->',p_object)
# if not isinstance(p_object,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):
# raise TypeError('must be int')
# # self.append(p_object)
# super().insert(index,p_object)
#
# l=List([1,2,3])
# # print(l)
# # l.append(4)
# # print(l)
#
# # l.append('5')
# print(l)
# # l.insert(0,-1)
# l.insert(0,'-1123123213')
# print(l) # def test(x:int,y:int)->int:
# return x+y
# print(test.__annotations__)
#
# print(test(1,2))
# print(test(1,'3'))
#
# def test(x,y):
# return x+y #不能用继承,来实现open函数的功能
# f=open('a.txt','w')
# print(f)
# f.write('1111111') #授权的方式实现定制自己的数据类型
import time class Open:
def __init__(self,filepath,m='r',encode='utf-8'):
self.x=open(filepath,mode=m,encoding=encode) self.filepath=filepath
self.mode=m
self.encoding=encode def write(self,line):
print('f自己的write',line)
t=time.strftime('%Y-%m-%d %X')
self.x.write('%s %s' %(t,line)) def __getattr__(self, item):
# print('=------>',item,type(item))
return getattr(self.x,item)
#
# f=Open('b.txt','w')
# # print(f)
# f.write('111111\n')
# f.write('111111\n')
# f.write('111111\n') f=Open('b.txt','r+')
# print(f.write)
print(f.read) res=f.read() #self.x.read()
print(res) print('=-=====>',f.read())
f.seek(0)
print(f.read())
# f.flush()
# f.close() 

  作业:

 #基于继承来定制自己的数据类型
class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
def append(self, p_object):
' 派生自己的append:加上类型检查'
if not isinstance(p_object,int):
raise TypeError('must be int')
super().append(p_object)
#
@property
def mid(self):
'新增自己的属性'
index=len(self)//2
return self[index] # l=List([1,2,3]) # print(l.mid) #基于授权来定制自己的数据类型: # class Open:
# def __init__(self,filepath,mode,encode='utf-8'):
# self.f=open(filepath,mode=mode,encoding=encode)
# self.filepath=filepath
# self.mode=mode
# self.encoding=encode # def write(self,line):
# print('write')
# self.f.write(line) # def __getattr__(self, item):
# return getattr(self.f,item) # # f=Open('a.txt','w')
# # f.write('123123123123123\n')
# # print(f.seek)
# # f.close()
# #
# # f.write('111111\n') # f=open('b.txt','w')
# f.write('bbbbbb\n')
# f.close()
# print(f) # class Foo:
# def test(self):
# pass
#
# print(getattr(Foo,'test'))
#
# obj=Foo()
# print(getattr(obj,'test')) class List:
def __init__(self,x):
self.seq=list(x) def append(self,value):
if not isinstance(value,str):
raise TypeError('must be str')
self.seq.append(value)
@property
def mid(self):
index=len(self.seq)//2
return self.seq[index]
def __getattr__(self, item):
return getattr(self.seq,item) def __str__(self):
return str(self.seq) l=List([1,2,3]) l.append('') print(l.mid)
l.insert(0,123123123123123123123123123)
# print(l.seq) print(l) obj.name='egon'
del obj.name

链接:详细

Python之面向对象反射的更多相关文章

  1. Python之面向对象-反射

    一.什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本省状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被 ...

  2. python基础-9__import__ 反射和面向对象基础 self 封装 继承(多继承顺序) 多态

    一 反射 python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删 ...

  3. python基础——面向对象进阶

    python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...

  4. python学习------面向对象的程序设计

    一 面向对象的程序设计的由来 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语言 ...

  5. 【转】Python之面向对象与类

    [转]Python之面向对象与类 本节内容 面向对象的概念 类的封装 类的继承 类的多态 静态方法.类方法 和 属性方法 类的特殊成员方法 继承层级关系中子类的实例对象对属性的查找顺序问题 一.面向对 ...

  6. Python OOP面向对象

    一.什么是面向对象的程序设计 1.面向过程 程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式. 优点是 ...

  7. Python 3 面向对象进阶

    Python 3 面向对象进阶 一.    isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的 ...

  8. python初始面向对象

    阅读目录 楔子 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 类命名空间与对象.实例的命名空间 类的组合用法 初识面向对象小结 面向对象的三大特性 继承 多态 封装 ...

  9. Python 基础 三 反射

    Python 基础 三 反射 今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己.在我们Python的面向对象中的反射是啥意思呢?就是通过字符串的形式操作对象相关的属性.python中的一 ...

随机推荐

  1. Uix Kit 快速建站前端开发套件-工具箱

    这个产品维护已经有一年了(由于业务需求不同,目前没有做中文版,产品本身是针对国外网站),自己本身是做UI出生,开发只是业余爱好,仅仅作为平时工作的需要.杂七杂八会一些前后端开发.并非职业码农! 我是一 ...

  2. Python中处理日期时间库的使用方法(转载)

    <本文来自公众号“大邓带你玩python”,转载> 用百分之20时间,学会解决百分之80的问题. 常用的库有time.datetime.其中datetime库是对time库的封装,所以使用 ...

  3. [CERC2017]Buffalo Barricades

    这个题目,扫描线+玄学** 大概操作就是用个扫描线从上往下扫. 博主有点懒,就直接贴代码了,但是我还是给大家贴个比较详细的博客,除了代码都可以看wym的博客,我基本上就是按wym大佬的思路来的,当然, ...

  4. BP神经网络算法改进

    周志华机器学习BP改进 试设计一个算法,能通过动态调整学习率显著提升收敛速度,编程实现该算法,并选择两个UCI数据集与标准的BP算法进行实验比较. 1.方法设计 传统的BP算法改进主要有两类: - 启 ...

  5. 01背包 Codeforces Round #267 (Div. 2) C. George and Job

    题目传送门 /* 题意:选择k个m长的区间,使得总和最大 01背包:dp[i][j] 表示在i的位置选或不选[i-m+1, i]这个区间,当它是第j个区间. 01背包思想,状态转移方程:dp[i][j ...

  6. oracle 创建表

    --创建表 create table browser_track( btId number not null , opend_id ) not null, url_address ) not null ...

  7. 5 Transforms 转移 笔记

    5 Transforms 转移 笔记   Transforms    Unfortunately, no one can be told what the Matrix is. You have to ...

  8. leetcode_238. Product of Array Except Self_思维

    https://leetcode.com/problems/product-of-array-except-self/ 给一个vector<int> nums,输出一个vector< ...

  9. Android(java)学习笔记190:ContentProvider使用之学习ContentProvider(内容提供者)的目的

    1. 使用ContentProvider,把应用程序私有的数据暴露给别的应用程序,让别的应用程序完成对自己私有的数据库数据的增删改查的操作. 2. ContentProvider的应用场景: 获取手机 ...

  10. Python3.0 操作MySQL数据库执行SQL语句

    py3不支持MySQLdb,需要导入pymysql模块 # coding: utf-8 # Team : Quality Management Center # Author:Carson # Dat ...