getattr和getattribute,getAttr
Python中处理属性的重要属性和函数是什么
处理属性的重要属性和函数
1、特殊属性
__class__:对象所属类的引用(即obj.__class__和type(obj)的作用相同)。Python中的某些特殊方法比如 __getattr__,只在对象的类中寻找,而不在实例中寻找。__dict__:一个映射,存储对象或类的可写属性。__slots__:类可以定义这个属性,限制实例有哪些属性。
2、内置函数
dir([object]):列出对象的大多数属性。getattr(object,name[,default]):从object对象中获取name字符串对应的属性。获取的属性可能来自对象所属的类或超类。hasattr(object,name):若object对象中存在指定的属性,或者能以某种方式(如继承)通过object对象获取指定的属性,返回True。setattr(object,name,value):把object对象指定属性的值设为value,前提是object对象能接受那个值。这个函数可能会创建一个新属性,或者覆盖现有的属性。var([object]):返回object对象的__dict__属性。
相关推荐:《Python视频教程》
3、特殊方法
__delattr__(self,name):只要使用del语句删除属性,就会调用这个方法。__dir__(self):把对象传给dir函数时调用,列出属性。__getattr__(self,name):仅当获取指定的属性失败,搜索过obj,Class和超类之后调用。__getattribute__(self,name):尝试获取指定的属性时总会调用这个方法。不过寻找的属性是特殊属性或特殊方法时除外。为了防止无限递归,__getattribute__方法的实现要使用super().__getattribute__(obj,name)。__setattr__(self,name,value):尝试设置指定的属性时总会调用这个方法。点号和setattr内置函数会触发这个方法。
相关推荐:
Python中的属性和特性是什么
python 对象属性名称与关键字冲突怎么办?
可以通过getattr函数来获取和设置这样的属性
但是如果手上有源码的话
最好是进行修改
比如追加下划线来避免这种情况出现
python getattribute、get、getattr、getitem等用法
__getattribute__
__getattribute__是属性访问拦截器,就是当类的属性被访问时,会自动调用类的__getattribute__方法。
参考代码:
代码执行过程中,当调用实例对象attribute的name属性时,不会直接打印,而是把name的值作为实参传进__getattribute__方法中,经过一系列操作后,再把name的值返回。
python中只要定义了继承object的类,就默认存在属性拦截器,只不过是拦截后没有进行任何操作,而是直接返回。
我们可以自己改写__getattribute__方法来实现相关功能,比如查看权限、打印log日志等。
getattr、hasattr、setattr
对象属性的判断。
参考代码:
__getattr__、__setattr__、__delattr__
类支持 . 操作来访问属性;定制功能:耗时、日志等等。
参考代码:
__getitem__、__setitem__、__delitem__
类支持通过[]来访问属性
参考代码:
__get__、__set__、__delete__
参考代码:
参考文档:
python中的__getattr__问题
关于python的内置方法,希望能用一个简单的例子帮到你:
=========test.py
class a(object):
name = "Jim"
def __setattr__(self,name,value):
self.__dict__[name] = value
def __getattr__(self,name):
return name
b = a()
print dir(b)
print b.__dict__
print b.name
print b.notexists
b.name = "change"
print dir(b)
print b.__dict__
print b.name
print b.notexists
===========运行结果========
%python test.py
['__class__', '__delattr__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'name']
{}
Jim
notexists
['__class__', '__delattr__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'name']
{'name': 'change'}
change
notexists
============================
可以看到刚开始的时候b的__dict__对象里面是空的没有东西,当我们使用b.name访问的时候直接访问到的之前定义好的name属性:"Jim"
当我们使用b.name = "change"后就默认调用了内置方法__setattr__,此时我并没有直接操作self.name属性,而是直接在修改了self.__dict__['name'] = 'change'.之后当我再用b.name访问的时候获得的就是__dict__中的name属性的值。
于是我们可以看到__getattr__方法首先是在__dict__中找属性名,然后在实例的属性中找 ,然后再调用__getattr__方法获得值。
希望能帮到你
python类的属性有哪几种?如何访问它们?
属性的访问机制
一般情况下,属性访问的默认行为是从对象的字典中获取,并当获取不到时会沿着一定的查找链进行查找。例如?a.x?的查找链就是,从?a.__dict__['x']?,然后是?type(a).__dict__['x']?,再通过?type(a)?的基类开始查找。
若查找链都获取不到属性,则抛出?AttributeError?异常。
一、__getattr__?方法
这个方法是当对象的属性不存在是调用。如果通过正常的机制能找到对象属性的话,不会调用?__getattr__?方法。
class?A:
a?=?1
def?__getattr__(self,?item):
print('__getattr__?call')
return?item
t?=?A()
print(t.a)
print(t.b)
#?output
1
__getattr__?call
b
二、__getattribute__?方法
这个方法会被无条件调用。不管属性存不存在。如果类中还定义了?__getattr__?,则不会调用?__getattr__()方法,除非在?__getattribute__?方法中显示调用__getattr__()?或者抛出了?AttributeError?。
class?A:
a?=?1
def?__getattribute__(self,?item):
print('__getattribute__?call')
raise?AttributeError
def?__getattr__(self,?item):
print('__getattr__?call')
return?item
t?=?A()
print(t.a)
print(t.b)
所以一般情况下,为了保留?__getattr__?的作用,__getattribute__()?方法中一般返回父类的同名方法:
def?__getattribute__(self,?item):
return?object.__getattribute__(self,?item)
使用基类的方法来获取属性能避免在方法中出现无限递归的情况。
三、__get__?方法
这个方法比较简单说明,它与前面的关系不大。
如果一个类中定义了?__get__(),?__set__()?或?__delete__()?中的任何方法。则这个类的对象称为描述符。
class?Descri(object):
def?__get__(self,?obj,?type=None):
print("call?get")
def?__set__(self,?obj,?value):
print("call?set")
class?A(object):
x?=?Descri()
a?=?A()
a.__dict__['x']?=?1??#?不会调用?__get__
a.x??????????????????#?调用?__get__
如果查找的属性是在描述符对象中,则这个描述符会覆盖上文说的属性访问机制,体现在查找链的不同,而这个行文也会因为调用的不同而稍有不一样:
如果调用是对象实例(题目中的调用方式),a.x?则转换为调用:。type(a).__dict__['x'].__get__(a, type(a))
如果调用的是类属性,?A.x?则转换为:A.__dict__['x'].__get__(None, A)
其他情况见文末参考资料的文档
四、__getitem__?方法
这个调用也属于无条件调用,这点与?__getattribute__?一致。区别在于?__getitem__?让类实例允许?[]?运算,可以这样理解:
__getattribute__适用于所有.运算符;
__getitem__适用于所有?[]?运算符。
class?A(object):
????a?=?1
????def?__getitem__(self,?item):
????????print('__getitem__?call')
????????return?item
t?=?A()
print(t['a'])
print(t['b'])
如果仅仅想要对象能够通过?[]?获取对象属性可以简单的:
def?__getitem(self,?item):
????return?object.__getattribute__(self,?item)
总结
当这几个方法同时出现可能就会扰乱你了。我在网上看到一份示例还不错,稍微改了下:
class?C(object):
????a?=?'abc'
????def?__getattribute__(self,?*args,?**kwargs):
????????print("__getattribute__()?is?called")
????????return?object.__getattribute__(self,?*args,?**kwargs)
????#????????return?"haha"
????def?__getattr__(self,?name):
????????print("__getattr__()?is?called?")
????????return?name?+?"?from?getattr"
????def?__get__(self,?instance,?owner):
????????print("__get__()?is?called",?instance,?owner)
????????return?self
????def?__getitem__(self,?item):
????????print('__getitem__?call')
????????return?object.__getattribute__(self,?item)
????def?foo(self,?x):
????????print(x)
class?C2(object):
????d?=?C()
if?__name__?==?'__main__':
????c?=?C()
????c2?=?C2()
????print(c.a)
????print(c.zzzzzzzz)
????c2.d
????print(c2.d.a)
????print(c['a'])
可以结合输出慢慢理解,这里还没涉及继承关系呢。总之,每个以?__get?为前缀的方法都是获取对象内部数据的钩子,名称不一样,用途也存在较大的差异,只有在实践中理解它们,才能真正掌握它们的用法。