博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python中的反射
阅读量:5863 次
发布时间:2019-06-19

本文共 3704 字,大约阅读时间需要 12 分钟。

什么是反射

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。

python面向对象中的反射就是通过字符串获取对象或者类的属性,进行操作~,主要是对这4个方法的应用:hasattr,getattr,setattr,delattr。

反射对象的属性和方法

class Person:    def __init__(self, name, age):        self.__name = name        self.__age = age    def __fun(self):        print(self.__class__)    def say(self):        print(self.__name + ' ' + str(self.__age))# 判断属性是否存在p = Person('baby', 18)print(hasattr(p, 'name'))                    # Falseprint(hasattr(p, '_Person__name'))   # Trueprint(hasattr(p, 'say'))                       # True# 获取属性fun = getattr(p, 'say')fun()                # baby 18,执行反射获取的方法name = getattr(p, '_Person__name')print(name)    # baby# 若是属性不存在则报错# age = getattr(p, 'age')   # 'Person' object has no attribute 'age'# 设置属性setattr(p, 'sex', 'male')       # 设置的是对象的属性,存放在对象的名称空间中# 这里设置的方法是普通方法,存放在对象的名称空间中,self.__name不会变形为 self._Person__name# setattr(p, 'show_name', lambda self: self.__name)   setattr(p, 'say_hello', lambda self: 'Hello ' + self._Person__name)print(p.__dict__)         # {'_Person__name': 'baby', '_Person__age': 18, 'sex': 'male', 'say_hello': 
at 0x10f7bf2f0>}print(p.say_hello(p)) # 不是绑定方法,需要手动传值# 删除属性delattr(p, 'sex')print(p.__dict__)# {'_Person__name': 'baby', '_Person__age': 18, 'say_hello':
at 0x10f7bf2f0>}# 若不存在该属性则报错# delattr(p, 'name') # AttributeError: name

Tip:

  • 通过对象设置的属性,不管是变量还是方法,都存放在对象的名称空间中;
  • 通过对象设置的方法仅仅是普通方法,调用的时候也不会自动传值(需要手动传值),且方法中不能使用对象的私有属性

反射类的属性和方法

class Person:    def __init__(self, name, age):        self.__name = name        self.__age = age        self.city = 'NB'    def __fun(self):        print(self.__class__)    def say(self):        print(self.__name + ' ' + str(self.__age))    @classmethod    def play(cls):        print(cls.__name__)    @staticmethod    def sleep():        print('sleep...')# 判断属性是否存在print(hasattr(Person, 'name'))                    # Falseprint(hasattr(Person, '_Person__name'))   # False,私有属性 __name,__age 属于对象print(hasattr(Person, 'say'))                       # True# 获取属性fun = getattr(Person, 'say')p = Person('baby', 18)fun(p)          # baby 18,等同于Person.say(p),需要手动传递self# 若是属性不存在# age = getattr(Person, 'age')   # 报错,'Person' object has no attribute 'age'# 设置属性setattr(Person, 'sex', 'male')    # 设置的是类的静态属性setattr(Person, 'show_city', lambda self: self.city)   # 这里通过类设置的方法为绑定到对象的方法,通过对象调用的时候能够自动传值(self)print(p.show_city())    # NB# setattr(Person, 'show_name', lambda self: self.__name)   # self.__name 不会自动转换为 self._Person__name# print(p.show_name())    # AttributeError: 'Person' object has no attribute '__name'# 删除属性delattr(Person, 'sex')   # 删除的是类的静态属性# 获取类方法getattr(Person, 'play')()   # 会完成自动传值,默认将Person作为第一个参数传递给play方法# 获取静态方法getattr(Person, 'sleep')()

Tip:

  • 通过类设置的属性,存放在类的名称空间中;
  • 通过类设置的方法为绑定到对象的方法,通过对象调用的时候,能够完成自动传值;同样方法内无法访问到私有变量(self.__属性 不会自动转换为self._类名__属性)

反射当前模块成员

import sysdef s1():    print('s1')def s2():    print('s2')this_module = sys.modules[__name__]# 判断模块中是否存在 s1 方法print(hasattr(this_module, 's1'))   # True# 获取模块中的方法并执行getattr(this_module, 's2')()           # s2

sys.modules[__name__] 也可以写成 sys.modules['__main__'],但是不建议这么写,因为当前的模块被导入到另外一个模块的时候,这个被导入的模块使用 sys.modules['__main__'] 就获取不到它的内存地址了~

 
操作的对象也可以是导入的模块

# module_testdef test():    print('from test')# test.pyimport module_testprint(hasattr(module_test,'test'))   # Truegetattr(module_test, 'test')()          # from test

isinstance 和 issubclass

isinstance 方法用来判断 一个对象 和 一个类之间的关系,即这个对象是不是由这个类实例化而来

class Person:    passp = Person()print(isinstance(p, Person))    # True

 

issubclass 用来判断两个类之间是否存在继承关系

class Father:    passclass Son(Father):    passprint(issubclass(Son, Father))    # True

.................^_^

转载于:https://blog.51cto.com/ljbaby/2348710

你可能感兴趣的文章
Directx11教程(60) tessellation学习(2)
查看>>
用Fedora构建自己的Linux发行版
查看>>
Windows和Linux环境下Memcached安装与配置
查看>>
优秀网页设计:20个立体动感的视差滚动效果网站
查看>>
PHP 字符串匹配算法 Sunday算法
查看>>
iptables 下实现 FTP 的 PASV 模式连接
查看>>
Windows 8常用快捷键
查看>>
[Yii Framework] Form with GET method
查看>>
scau实验题 8600 骑士周游问题(有障碍物)
查看>>
帮助你在不同尺寸屏幕下浏览网站效果的工具 - Responsivator
查看>>
windows server 2003 可以通过IP访问网络,而无法打开网页
查看>>
NYOJ236心急的C小加
查看>>
[LeetCode] Unique Paths
查看>>
InstallShield 2010打包
查看>>
在src文件中寻找短信数据库表
查看>>
java的getClass()函数
查看>>
JS 身份证校验
查看>>
查询被占用的端口
查看>>
SharePoint2013 Workflow Manager配置
查看>>
Nginx 1.2.6 稳定版发布
查看>>