在做程序开发中,我们常常会遇到这样的需求:需要执行对象里的某个方法,或需要调用对象中的某个变量,但是由于种种原因我们无法确定这个方法或变量是否存在,这是我们需要用一个特殊的方法或机制要访问和操作这个未知的方法或变量,这中机制就称之为反射

反射:用字符串的方式去访问对象的属性,调用对象的方法python中一切皆对象,都可以使用反射

  1. hasattr(obj, name):检查 obj 对象是否包含名为 name 的属性或方法。
  2. getattr(object, name[, default]):获取 object 对象中名为 name 的属性的属性值。
  3. setattr(obj, name, value,/):将obj 对象的 name 属性设为 value。

hasattr

判断一个对象是否有name属性或者name方法。有就返回True,没有就返回False

class Person(object):
    def __init__(self,name):
        self.name = name
    def talk(self):
        print("%s正在交谈"%self.name)

p = Person("santa")
print(hasattr(p,"talk"))    # True。因为存在talk方法
print(hasattr(p,"name"))    # True。因为存在name变量
print(hasattr(p,"abc"))     # False。因为不存在abc方法或变量

getattr

获取对象的属性或者方法,如果存在则打印出来。hasattrgetattr配套使用

class Person(object):
    def __init__(self,name):
        self.name = name
    def talk(self):
        print("%s正在交谈"%self.name)
p = Person("santa")

n = getattr(p,"name")   # 获取name变量的内存地址
print(n)                # 此时打印的是:laowang

f = getattr(p,"talk")   # 获取talk方法的内存地址
f()                     # 调用talk方法

# 我们发现getattr有三个参数,那么第三个参数是做什么用的呢?
s = getattr(p,"abc","not find")
print(s)
#若属性不存在,则返回默认值(第三个参数)

打印结果:

santa
santa正在交谈
not find

setattr

给对象的属性赋值,若属性不存在,先创建后赋值

def abc(self):
    print("%s正在交谈"%self.name)

class Person(object):
    def __init__(self,name):
        self.name = name

p = Person("santa")
setattr(p,"talk",abc)   # 将abc函数添加到对象中p中,并命名为talk
p.talk(p)               # 调用talk方法,因为这是额外添加的方法,需手动传入对象
#结果
#santa正在交谈
setattr(p,"age",30)     # 添加一个变量age,赋值为30
print(p.age)            # 打印结果:30

delattr

删除该对象指定的一个属性。注意:不能用于删除方法

class Person(object):
    def __init__(self,name):
        self.name = name
    def talk(self):
        print("%s正在交谈"%self.name)

p = Person("laowang")

delattr(p,"name")         # 删除name变量
print(hasattr(p,'name'))  #False

反射的应用

# 反射应用:
根据用户输入进行动态调用
class FileControl:

    def run(self):
        while True:
            # 让用户输入上传或下载功能的命令:
            user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip()

            # 通过用户输入的字符串判断方法是否存在,然后调用相应的方法
            if hasattr(self, user_input):
                func = getattr(self, user_input)
                func()
            else:
                print('输入有误!')

    def upload(self):
        print('文件正在上传...')

    def download(self):
        print('文件正在下载...')

file_control_obj = FileControl()
file_control_obj.run()

这就是python的反射,它的核心本质其实就是利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动!

__import__(了解)

要是想导入不同目录下的函数,可以这样:动态导入模块

def run():
    inp = input("请输入您想访问页面的url:  ").strip()
    modles, func = inp.split("/")
    obj = __import__("lib." + modules, fromlist=True)  # 注意fromlist参数  modles是url
    if hasattr(obj, func):
        func = getattr(obj, func)
        func()
    else:
        print("404")

if __name__ == '__main__':
    run()

思考:

可能有人会问python不是有两个内置函数exec和eval吗?他们同样能够执行字符串。比如:

exec("print('haha')")
结果:
haha

那么直接使用它们不行吗?非要那么费劲地使用getattr,__import__干嘛?

其实,在上面的例子中,围绕的核心主题是如何利用字符串驱动不同的事件,比如导入模块、调用函数等等,这些都是python的反射机制,是一种编程方法、设计模式的体现,凝聚了高内聚、松耦合的编程思想,不能简单的用执行字符串来代替。当然,exec和eval也有它的舞台,在web框架里也经常被使用。

hasattr、getattr、setattr、delattr、反射的更多相关文章

  1. hasattr getattr setattr delattr --> (反射)

    class Room: def __init__(self,name): self.name = name def big_room(self): print('bigroot') R = Room( ...

  2. isinstance/type/issubclass的用法,反射(hasattr,getattr,setattr,delattr)

    6.23 自我总结 面向对象的高阶 1.isinstance/type/issubclass 1.type 显示对象的类,但是不会显示他的父类 2.isinstance 会显示的对象的类,也会去找对象 ...

  3. python 内置函数的补充 isinstance,issubclass, hasattr ,getattr, setattr, delattr,str,del 用法,以及元类

    isinstance   是 python中的内置函数 , isinstance()用来判断一个函数是不是一个类型 issubclass  是python 中的内置函数,  用来一个类A是不是另外一个 ...

  4. python反射hasattr getattr setattr delattr

    反射 : 是用字符串类型的名字 去操作 变量 相比于用eval('print(name)') 留有 安全隐患 反射 就没有安全问题 hasattr 语法: hasattr(object, name)o ...

  5. Python hasattr,getattr,setattr,delattr

    #!/usr/bin/env python # -*- coding:utf-8 -*- # 作者:Presley # 邮箱:1209989516@qq.com # 时间:2018-11-04 # 反 ...

  6. 反射hasattr; getattr; setattr; delattr

    hasattr(obj,name_str):#判断一个对象obj里面是否有对应的name_str字符串的方法,返回True或者Falsegetattr(obj,name_str):#根据字符串去获取对 ...

  7. python动态函数hasattr,getattr,setattr,delattr

    hasattr(object,name) hasattr用来判断对象中是否有name属性或者name方法,如果有,染回true,否则返回false class attr():     def fun( ...

  8. Python的getattr(),setattr(),delattr(),hasattr()及类内建__getattr__应用

    @Python的getattr(),setattr(),delattr(),hasattr() 先转一篇博文,参考.最后再给出一个例子 getattr()函数是Python自省的核心函数,具体使用大体 ...

  9. 反射之hasattr() getattr() setattr() 函数

    Python的hasattr() getattr() setattr() 函数使用方法详解 hasattr(object, name)判断object中有没有一个name字符串对应的方法或属性,返回B ...

  10. 【转】Python的hasattr() getattr() setattr() 函数使用方法详解

    Python的hasattr() getattr() setattr() 函数使用方法详解 hasattr(object, name)判断一个对象里面是否有name属性或者name方法,返回BOOL值 ...

随机推荐

  1. 数据可视化-matplotlib包

    pyplot官网教程https://matplotlib.org/users/pyplot_tutorial.html #导入matplotlib的pyplot模块 import matplotlib ...

  2. 克隆系统后如何重新清除SID

    为什么要清除SID? SID(Security Identifiers,安全标识符)是Windows中标识用户.组和计算机的唯一的号码,Windows操作系统通过SID对计算机和用户进行识别.用户的权 ...

  3. Noip2015Day2T3 运输计划

    题目链接 problem 一棵n个点带边权的树,有m个条路径.选择一条边,将其权值变为0,使得长度最长的路径长度最小.求该长度最小为多少. solution 其实仔细一想并不难. 删除一条边会导致所有 ...

  4. Windows许可证 即将过期

    最近打开电脑,系统总是自动弹出Windows许可证即将过期的弹窗,现在总结方法如下. 命令都是在运行窗口输入的打开方式:win+R组合键或者右键点击win10开始菜单,点击“运行”查看系统版本:win ...

  5. ASP.NET Core 中基于 API Key 对私有 Web API 进行保护

    这两天遇到一个应用场景,需要对内网调用的部分 web api 进行安全保护,只允许请求头账户包含指定 key 的客户端进行调用.在网上找到一篇英文博文 ASP.NET Core - Protect y ...

  6. 基于Docker的Consul服务发现集群搭建

    在去年的.NET Core微服务系列文章中,初步学习了一下Consul服务发现,总结了两篇文章.本次基于Docker部署的方式,以一个Demo示例来搭建一个Consul的示例集群,最后给出一个HA的架 ...

  7. SpringBoot系列之@PropertySource用法简介

    SpringBoot系列之@PropertySource用法简介 继上篇博客:SpringBoot系列之@Value和@ConfigurationProperties用法对比之后,本博客继续介绍一下@ ...

  8. mysql中的ifnull()函数判断空值

    我们知道,在不同的数据库引擎中,内置函数的实现.命名都是存在差异的,如果经常切换使用这几个数据库引擎的话,很容易会将这些函数弄混淆. 比如说判断空值的函数,在Oracle中是NVL()函数.NVL2( ...

  9. go-家庭收支记账软件例子

    家庭收支记账软件项目 项目需求说明 1) 模拟实现基于文本界面的<家庭记账软件> 2) 该软件能够记录家庭的收入.支出,并能够打印收支明细表 项目的界面 看代码效果 项目代码实现 实现基本 ...

  10. Python笔记:设计模式之代理模式

    代理通常就是一个介于寻求方和提供方之间的中介系统.其核心思想就是客户端(寻求方)没有直接和提供方(真实对象)打交道,而是通过代理对象来完成提供方提供的资源或操作. 代理其实就是封装实际服务对象的包装器 ...