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

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

class Foo:passobj = Foo()
isinstance(obj, Foo)

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

class Foo:passclass Bar(Foo):passissubclass(Bar,Foo)

反射

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

# 反射
class People:country = "china"def __init__(self,name):self.name = namedef walk(self):print("%s is walking" % self.name)p = People("egon")
print(p.__dict__)           #     {'name': 'egon'}
print(People.__dict__)       # {'__weakref__': <attribute>,...... '__module__':  'country': 'china'}# hasattr检测是否含有某属性
print(hasattr(p, "name"))          # True
print(hasattr(p, "country"))       # True
print(hasattr(p, "walk"))          # True
print(hasattr(People, "name"))     # False
print(hasattr(People, "country"))  # True
print(hasattr(People, "walk"))     # True# getattr(obj,name)获取属性
n1 = getattr(p,"country")  # china
n2 = getattr(p,"name")     # egon
n3 = getattr(p,"walk")     # bound method
n4 = getattr(People,"country") # china
n5= getattr(People,"name")  # AttributeError,没这个属性
n6= getattr(People,"walk")    # function method# setattr(x, y, v)设置属性
setattr(p, "age", 18)
setattr(p, "func", lambda self:self.name + "_pirate")
print(type(p.func))  # <class 'function'>,setattr设置的是类属性,不是绑定对象的方法
print(p.func(p))     # egon_pirate
print(p.age)         # 18# delattr(x, y) 删除属性
delattr(p, "name")
delattr(p, "walk") # AttributeError,不能删除绑定方法
delattr(People, "walk")
delattr(p,"fa")      # 没有属性也报错

反射当前模块的属性

##反射当前模块的属性
import sys
x = 1111
class Foo:pass
def s1():print("from function s1")def s2():print("S2")this_module = sys.modules[__name__]  # 拿到当前模块的属性print(this_module)                # <module '__main__' from 'C:/workspace/test.py'>
print(hasattr(this_module,"s1"))  # True
print(hasattr(this_module,"s2"))  # True
print(hasattr(this_module,"s3"))  # False
print(hasattr(this_module, "Foo")) # True
f = getattr(this_module,"s1")
f()    # from function s1

反射当前模块属性应用之增删改查

# 应用之增删改查
def add():print("---add function---")def delete():print("---delete function---")def modify():print("---modify function---")def search():print("---search function---")import sys
this_module = sys.modules[__name__]
# print(this_module.__dict__)      # 'search': <function search at 0x017A5228>...
while True:cmd = input(">>:").strip()if hasattr(this_module, cmd):      # 判断当前模块是否有这个属性f = getattr(this_module, cmd)  # 得到该属性f()   # 运行函数else:print("没有该功能请继续输入")

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

# FtpClient.py文件
class FtpClient:' ftp客户端,但是还么有实现具体的功能 'def __init__(self,addr):print('正在连接服务器[%s]' %addr)self.addr=addr# def download(self):#     print("download...")
# FtpServer文件
from FtpClient import FtpClient
data = FtpClient("192.168.1.123")
if hasattr(data, "download"):func = getattr(data, "download")func()   # FtpClient存在该属性,则拿到执行,不存在执行else
else:print("不存在此方法")print("处理其他逻辑")

通过字符串导入模块

# 通过字符串导入模块
# 推荐使用
import importlib
t = importlib.import_module("time")
print(t.strftime("%Y-%m-%d %X")) # 2017-04-24 15:53:42# 不推荐
t = __import__("time")
print(t.strftime("%Y-%m-%d %X"))  # 2017-04-24 15:54:26

**__setattr__,__delattr,__getattr**

#**__setattr__,__delattr__,__getattr__基本用法**
class Foo:def __init__(self,name):self.name = namedef __getattr__(self, item):   # 属性不存在才触发print("getattr--->%s %s" % (item, type(item)))def __setattr__(self, key, value):if not isinstance(value,str):  # 限制了所有设置属性必须为str,和@property不同raise TypeError("must be str")print("----------setter")self.__dict__[key] = valuedef __delattr__(self, item):   # __delattr__删除属性的时候会触发print("-------------deltter")self.__dict__.pop(item)f = Foo("egon")
# __getattr__只有在使用点调用属性且属性不存在的时候才会触发
print(f.name)   # egon, 正常执行
print(f.fjkad)  # getattr--->fjkad <class 'str'>,找不到触发__getattr__# __setattr__添加/修改属性会触发它的执行
f.nickname = "邹润成"
print(f.__dict__)  # {'name': 'egon', 'nickname': '邹润成'}
f.__dict__['a']=3  # 可以直接修改属性字典,来完成添加/修改属性的操作# __delattr__删除属性的时候会触发
del f.nickname
print(f.__dict__)  # {'name': 'egon'}

定制自己的数据类型

python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识
使用继承定制自己的数据类型

# 基于继承标准类型定制自己的数据类型
class List(list):def append(self, p_object):if not isinstance(p_object, int): # 为append方法,进行类型限制 raise TypeError("must be int")super().append(p_object)@propertydef mid(self):"新增加的属性,取中间值"index = len(self)//2return self[index]a = List([1, 2, 3])
a.append(4)
a.append(5)
# a.append("5") # TypeError: must be int
print(a)      # [1, 2, 3, 4, 5]
print(a.mid)  # 3

使用授权的方法定制数据类型

# 作业:
#   基于授权定制自己的列表类型,要求定制的自己的__init__方法,
#   定制自己的append:只能向列表加入字符串类型的值
#   定制显示列表中间那个值的属性(提示:property)
#   其余方法都使用list默认的(提示:__getattr__加反射)
class LIST:def __str__(self):return str(self.seq)def __init__(self,*args):self.seq = list(*args)def append(self, value):if not isinstance(value, str):raise TypeError("必须传字符串")self.seq.append(value)@propertydef mid(self):index = len(self.seq)//2return self.seq[index]def __getattr__(self, item):return getattr(self.seq, item)l = LIST(["1","2","3"])
l.append("4")
l.append("5")
print(l)        # ['1', '2', '3', '4', '5']
print(l.mid)    # 3
print(l.pop())  # 5
print(l)        # ['1', '2', '3', '4']

使用授权的方法模拟日志

# 不使用继承模拟日志
import time
class Open:def __init__(self,filepath,mode="r",encoding="utf8"):self.x = open(filepath, mode=mode, encoding=encoding)self.filepath = filepathself.modde = modeself.encoding = encodingdef write(self, line):print("from f ", line)t = time.strftime("%Y-%m-%d %X")self.x.write("%s %s\n" % (t, line))f = Open("a.txt", "w", "utf8")
f.write("111111111")
f.write("222222222")
f.write("333333333")

增强版

# 加强版
import time
class Open:def __init__(self,filepath,mode="r", encoding="utf8"):self.x = open(filepath, mode=mode, encoding=encoding)self.filepath = filepathself.mode = modeself.encoding = encodingdef write(self, line):print("from f ", line)t = time.strftime("%Y-%m-%d %X")self.x.write("%s %s\n" % (t, line))def __getattr__(self, item):return getattr(self.x, item)f = Open("a.txt")
a = f.read()
print(a)
# 2017-04-24 17:15:36 111111111
# 2017-04-24 17:15:36 222222222
# 2017-04-24 17:15:36 333333333

转载于:https://www.cnblogs.com/zouruncheng/p/6758123.html

面向对象-反射和__getattr__系列相关推荐

  1. Python面向对象反射,双下方法

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

  2. python之面向对象反射和双下方法

    面向对象之反射,双下方法 反射 定义:主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python中一切皆对象(都 ...

  3. python全栈开发基础【第十七篇】面向对象反射和内置方法

    一.静态方法(staticmethod)和类方法(classmethod) 类方法:有个默认参数cls,并且可以直接用类名去调用,可以与类属性交互(也就是可以使用类属性) 静态方法:让类里的方法直接被 ...

  4. python面向对象教程_Python入门系列教程3-面向对象

    课程咨询.获取课件.技术交流直接加入博学谷在线学习:631731828 课程简介 本课程是Python系列入门课程的第三阶段,该阶段我们会学习面向对象(OOP)这一重要的编程思想.学习的知识点主要包括 ...

  5. python面向对象 : 反射和内置方法

    一. 反射 1. isinstance()和issubclass() isinstance( 对象名, 类名) : 判断对象所属关系,包括父类  (注:type(对象名) is 类名 : 判断对象所属 ...

  6. 我们程序员眼中的对象-看完华华的文章妈妈再也不担心我找不到对象了-Java面向对象编程思想理解系列(1)

    大家好!!!我叫霜华,是一个帅到没天理 骚里骚气,热爱人生与绿色 是一个不像程序员的程序员 作为一个在java这门领域沉迷一年半的人,如今在技术栈广度和深度 还是业务能力在客观层面讲确实进步迅速 (可 ...

  7. JAVa面向对象--反射

    反射就是把就java中的各种成为映射想成java类.例如:众多的人用一个person类来表示,那么众多的java类就用一个class类来表示. 反射也称为对类的解剖.把类的各个组成部位映射成一个个相应 ...

  8. 面向对象 -- 反射(详细)

    使用对象反射 obj . 属性名 obj . 方法名() 可以直接适用对象的方法和属性 当我们只有字符串数据类型的内容的时候 可以使用 getattr(对象名,'方法名')() 来调用方法 getat ...

  9. Java基础系列五 面向对象程序设计

    Java基础系列第一章 初识Java语言 Java基础系列第二章 Java语言基础 Java基础系列第三章 Java流程控制 Java基础系列第四章 Java数组与字符串 Java基础系列第五章 面向 ...

  10. php 反射对象属性,php面向对象之反射功能的用法详解

    这篇文章主要介绍了php面向对象之反射功能与用法,结合实例形式简单分析了php5面向对象反射的概念及具体用法,需要的朋友可以参考下 本文实例讲述了php面向对象之反射功能与用法.分享给大家供大家参考, ...

最新文章

  1. mysql数据库21_Mysql5.7.21安装文档
  2. 白话Elasticsearch02- 结构化搜索之filter执行原理bitset机制与caching机制
  3. matlab恢复默认界面布局
  4. 统一建模语言(UML)介绍
  5. 如何确定python开发环境已经配置好_python学习第一天:window安装python开发环境完整篇...
  6. 记录部件中GetFieldControlByFieldName(字段值样式设置)用法
  7. Cracer渗透-windows基础(系统目录,服务,端口,注册表)
  8. C++程序员应该掌握的东西
  9. 按clear按钮清空两个文本框的内容,按copy按钮时将Source文本框的内容复制到Target文本框,按close按钮结束程序的运行
  10. baidu__git_android
  11. Crossin先生的微信打飞机游戏(4)
  12. 提取Flash芯片信息
  13. ElasticJob 快速上手
  14. python控制步进电机代码tx2_步进电机按键控制.lst
  15. 什么是电影衍生品,电影衍生品是用来干嘛的?
  16. 【学习笔记】别怕,EXCELVBA其实很简单(第2版)
  17. k8s单节点无法启动pod
  18. Go:Aho-Corasick 算法(附完整源码)
  19. Word如何添加批注
  20. 三星手机直连电脑Samsung Flow

热门文章

  1. JS中的Error对象
  2. 原生html如何发送网络请求,原生JS向服务器发送GET请求
  3. php get header url,php函数get_headers是HEAD请求还是GET请求
  4. matplotlib制作多张图
  5. Android各版本代号、版本号、API/NDK级别、发布时间及市场份额
  6. 常用命令2——VNC
  7. [LeetCode]41.First Missing Positive
  8. 你学会测试了吗(1):推荐工具
  9. 诸如北京现代 只有四个轮子和一电瓶由中国制造(转自新华网)
  10. python 并发编程 多线程 守护线程