分享下自己最近对python的attribute lookup的学习, 也顺便做下记录。如果有说的不对的请拍砖!
1. python会为所有(更准确的说是所有非built-in对象)对象包括class和instance创建一个__dict__属性,
这个属性是一个dict类型, 存储的是这个对象所有的user-provided的属性名字和属性对象的对应关系,
包括一些属性值和函数等等。这个__dict__的作用除了可以让你了解到里面存储的是神马东西以外,
你也可以在程序里面遍历、设置__dict__里面的值。其实这个__dict__就像metaclass里面继承type的时候
要实现的__init__或者__new__方法里面的最后一个参数,只不过metaclass可以允许你在类创建之前就能
访问并且这是这个值了。不过也有例外的情况,
* 特殊的__dict__属性的情况:
1) 如果class里面定义__slots__属性的话,它的instance将不会拥有__dict__属性,
这个比较特殊。后面再讲__slots__.
2) 如果是python built-in的对象,像dict、list、int等的__dict__属性都是一个dictproxy对象,一个类似
dict的对象, 你可以通过这样来看看里面有神马东西:
for k, v in dict.__dict__.items():
print k
print v
print '*' * 20
* 从对象的继承链来看搜索属性的顺序:
1) 看obj.__dict__有没有 --->(没有) 2) 看obj.__class__.__dict__有没有 --->(没有) 3) 看obj.__class__.__base__有没有
--->(没有) 4) raise AttributeError
* 从python的一些内部函数来看属性的获取顺序:
1) object.__getattribute__(self, name) --->(没有name) 2)[optional, if offered] object.__getattr__(self, name)
|
|
(有name)
3) 看下改属性是否是descriptor, 如果是,那么调用descriptor的__get__方法返回,
如果不是,则直接将这个属性值返回。
当调用a.x这样的语法的时候,会首先调用a.__getattribute__('x')这样的方法,找到就检查该属性是否
是descriptor,是的话就调用它的__get__方法返回了, 不是descriptor的话就直接返回该属性。
如果也找不到x属性,那么就看下是否定义了__getattr__方法,有的话就调用__getattr__方法.
如果最后找不到的话就会抛AttributeError的错误!
可以用这个例子看看:(暂时忽略descriptor对属性查找的影响)
[http://mail.python.org/pipermail/python-dev/2010-March/098562.html]
(关于__getattribute__ & __getattr__的说明可以查看这里:
http://docs.python.org/reference/datamodel.html#object.__getattr__)
class A(object):
def __getattribute__(self, name):
print "A getattribute", name
#raise AttributeError('A error') #test1
return object.__getattribute__(self, name) #test2
def __getattr__(self, name):
print "A getattr", name
return "hello A"
class B(A):
def __getattribute__(self, name):
print "B getattribute", name
return super(B, self).__getattribute__(name)
def __getattr__(self, name):
print "B getattr", name
return "hello B"
print A().obj
print "-" * 20
print B().obj
print "-" * 20
print getattr(B(), "obj")
print "-" * 20
print object.__getattribute__(B(), "obj") # DOES NOT CALL __getattr__() !!!
=======
output
======
A getattribute obj
A getattr obj
hello A
--------------------
B getattribute obj
A getattribute obj
B getattr obj
hello B
--------------------
B getattribute obj
A getattribute obj
B getattr obj
hello B
--------------------
Traceback (most recent call last):
File "./attrs_test.py", line 35, in <module>
print object.__getattribute__(B(), "obj") # DOES NOT CBLL __getattr__() !!!
AttributeError: 'B' object has no attribute 'obj'
** 分析:
上面的例子证明了之前说的__getattribute__和__getattr__的调用顺序,而且假设你把#test1
的那段raise注释打开, 把#test2的代码注释掉的话,你会发现结果是一样的,这就说明python
内部应该还有一个类似总控的地方捕捉到__getattribute__抛出来的AttributeError异常(其他异常
是不行的)然后调用__getattr__函数了。 而最后一步:
print object.__getattribute__(B(), "obj")
则是因为它并不是经过实例B()的点属性语法的,所以不是走的上面的流程,所以直接报错了
** __getattribute__ & __getattr__的作用:
说了关于属性的查找过程,对我们的作用就是当我们需要重写获取属性的途径、方法的时候,
我们可以重写__getattribute__方法来实现,要注意的是在__getattribute__函数里面要为了
避免递归调用实例的点属性,建议调用父类的或者最上层的object的__getattribute__方法.
2 关于__slots__的[http://docs.python.org/reference/datamodel.html#slots]
1) 如果需要创建大量的实例(来自同一个类)的话,可以避免在每个类里面都保存__dict__来存储实例属性,可省空间.
2) 如果你要禁止在实例被创建之后会被动态添加属性的话,也就是你的属性只是可读的.可以用__slots__来预先定义.
但是继承自有定义__slots__的子类是不受父类的__slots__影响的, 所以如果要继续有效,必须所有的子类都定义跟
父类一样的__slots__
3) __slots__相当于为每个它定义的属性值写好了get和set的descriptor属性方法。所以A.a = 1 和print A.a才会生效。
4) 凡是定义了类的静态属性__slots__, 比如:
class A(object):
__slots__ = ['x', 'y']
那么A的实例就不能动态定义除了x和y之外的其他属性了,会报错。 而且实例里不会有__dict__属性。
3 获取属性或者设置属性的时候最好是用setattr和getattr函数,因为他们内部帮你处理好了很多事情,比如getattr能
自动识别descriptor等. 判断是否有该属性的话可以用hasattr
4 用__getattribute__实现了一个常量类,用于定义常量值和它对应的描述的,值可以通过点属性方式获取,
或者有些web界面有需要渲染对应值和它的中文描述的对应关系的,例如web界面上的select框就很常见。
这个常量类会提供这样一些有用的方法 更好的针对web应用.
比如用户输入了一个值,我们需要判断它是否在你定义的常量集合的合法值里面。
具体代码在附件的const.py里面
分享到:
相关推荐
主要介绍了Python 从attribute到property详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
精心整理的Python属性和方法处理技术
python3 server.py 127.0.0.1 8888 Traceback (most recent call last): File “server.py”, line 83, in main() File “server.py”, line 76, in main os.exit() AttributeError: module ‘os’ has no ...
主要跟大家介绍了关于在Python3下错误AttributeError: 'dict' object has no attribute 'iteritems'的分析与解决方法,文中介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
文章目录17 python生成词云1.安装Wordcloud库2.Wordcloud库简介3.词云绘制词云绘制步骤词云参数调整4.中英文词云绘制5.实例(政府工作报告词云) 17 python生成词云 1.安装Wordcloud库 使用python生成词云,需要首先...
基于属性的访问控制模型及其展望Attribute-Based Access Control Models and Beyond 云计算
python 的pmw模块 1.3.2python 的pmw模块 1.3.2python 的pmw模块 1.3.2python 的pmw模块 1.3.2python 的pmw模块 1.3.2python 的pmw模块 1.3.2
Tensorflow版 fasterrcnn的cpython_bbox 适用于 python36 win64位的机器
(用于曲线secp256k1上EC操作的实验性和优化C库)的Python FFI绑定。 安装 pip install secp256k1 预编译的二进制包(轮子) 预编译的二进制轮子可在Linux上用于Python 2.7、3.3、3.4和3.5。 要利用这些优势,您...
但在Geany中调用matplotlib绘图时出现attributeerror :module ‘numbers’has no attribute “Integral"错误。 原因是:同一个python代码文件夹里有一个名为numbers的代码文件(可能是自己之前的代码文件命名为...
python库。 资源全名:set-package-attribute-0.2.4.tar.gz
PEP 520: Preserving Class Attribute Definition Order PEP 468: Preserving Keyword Argument Order New dict implementation PEP 523: Adding a frame evaluation API to CPython PYTHONMALLOC environment ...
Python 中使用package时,出现循环导入问题十分常见,我们创建如下package来说明这个问题: pkg ├── __init__.py ├── module_a.py └── module_b.py 其中, __init__.py 将pkg指定为一个Python package ...
Through lots of hands-on examples, you’ll master core practices like handling multiple vector file formats, editing geometries, applying spatial and attribute filters, working with projections, and ...
AttributeError: module 'tensorflow.compat.v1' has no attribute 'contrib'的问题您具体怎么解决问题具体解决的seq_loss.py文件
补充知识:Pandas使用DataFrame出现错误:AttributeError: ‘list’ object has no attribute ‘astype’ 在使用Pandas的DataFrame时出现了错误:AttributeError: ‘list’ object has no attribute ‘astype’ 代码...
资源分类:Python库 所属语言:Python 资源全名:python-didl-lite-1.1.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
包含2篇attribute高级应用文章,以及相应的代码。 代码关键处,都有详细注释。 看过后,你会对attribute,context有更深刻的认识