惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
B
Blog
腾讯CDC
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - Franky
罗磊的独立博客
月光博客
月光博客
Jina AI
Jina AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
G
Google Developers Blog
V
Visual Studio Blog
I
InfoQ
有赞技术团队
有赞技术团队
D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19)
Python的反射:getattr
微信公众号 · 2017-02-18 · via 陈少文的网站

Please enable Javascript to view the contents

1. 应用场景

  1. 通过配置文件,控制程序运行时的流程。配置文件中常保存的是,字符串,而不是对象
  2. 调试程序时,查看对象的全部属性值
  3. 动态模块的导入

对于第一种场景,广泛被采用的是反射。在Java的很多框架中都使用了反射机制,Python实现的Web框架Django中,也有应用。比如url的路由。第二种场景,手动添加输出某个对象object类的属性值,非常的麻烦,而且不全。这时,可以使用dir(object)列出全部属性,然后使用反射来访问。第三中场景,通过反射也能实现。

2. Python的反射

通过反射,可以将字符串和对象的属性关联起来。通过dir(object),可以查看对象obejct的属性列表。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# -*- coding: utf-8 -*-
class Person:
    '''
    Python反射的一个举例
    '''
    count = 0

    def __init__(self, name="none", salary="0"):
        self.name = name
        self.salary = salary
        Person.count += 1

    def getName(self):
        print "i am in getName() function"
        return self.name


>>> p = Person(name="csw")
>>> dir(p)
['__doc__', '__init__', '__module__', 'count', 'getName', 'name', 'salary']
>>> hasattr(p, 'count')
True
>>> getattr(p, 'count')
1
>>> getattr(p, 'getName')()
i am in getName() function
csw
>>> setattr(p, 'ModifiedName', 'name')
None
>>> delattr(p, 'name')
None
>>> dir(p)
['ModifiedName', '__doc__', '__init__', '__module__', 'count', 'getName', 'salary']
>>> getattr(p, 'getName')()
AttributeError: Person instance has no attribute 'name'

2.1 getattr

方式:getattr(object,‘name‘,‘default’)

说明:如果存在name的属性方法,则返回name的属性方法,否则返回default的属性方法。

2.2 hasattr

方式:hasattr(object, ’name‘)

说明:判断对象object是否包含名为name的属性方法,存在则返回True,否则返回False。hasattr是通过调用getattr(ojbect, ’name‘)是否抛出异常来实现)。

2.3 setattr

方式:setattr(object,‘name’,’default‘)

说明:设置对象object的name属性值为default,如果没有name属性,那么创建一个新的属性。

2.4 delattr

方式:delattr(object,’name’)

说明:删除对象object的name属性值。

3. Python的反射实现

globals( )函数返回字典{ key:value },key是对象的名称,value是对象的实例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>,
 '__file__': 'E:/code/lab/python-reflection/exapmle.py',
 '__package__': None, 'Person': <class __main__.Person at 0x00215FB8>,
'__name__': '__main__', '__doc__': None}

>>> import test
{'__builtins__': <module '__builtin__' (built-in)>,
 '__file__': 'E:/code/lab/python-reflection/exapmle.py',
'__package__': None, 'Person': <class __main__.Person at 0x02045FB8>,
 'test': <module 'test' from 'D:\Python2711\lib\test\__init__.pyc'>,
'__name__': '__main__', '__doc__': None}

>>> globals()['test']
<module 'test' from 'D:\Python2711\lib\test\__init__.pyc'>

在执行 import test之后,可以看到新增了 test 的 key。可以利用这一点实现类似 Java 中,Class.forName()的功能。但是这种方法,使用之前必须先 import,否则会抛出异常。

Python中提供了 __import__(“functionName”)函数,传入参数“functionName”,就可以导入functionName模块。然后结合getattr函数进行相关的调用。

4. 为什么不直接用 exec和eval

熟悉python的同学应该知道,exec和eval语句,也可以用来执行储存在字符串或文件中的Python语句。
比如:

1
2
3
4
>>> eval('2*3')
6
>>> eval("2+3")
5

那么为什么还要反射呢?使用exec和eval能够实现相同的功能,但是反射是一种编程方法、是设计模式的体现。反射凝聚了高内聚、低耦合的软件设计思想,不能简单的使用执行字符串的函数替代。


微信公众号