程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Differences of several attribute access in Python

編輯:Python

start
python Provides a series of special methods related to property access :__get__, __getattr__, __getattribute__, __getitem__. This article expounds their differences and usages .

Property access mechanism
In general , The default behavior of property access is to get from the object's dictionary , And when it is not available, it will search along a certain search chain . for example a.x The search chain of is , from a.__dict__['x'] , And then there was type(a).__dict__['x'] , Re pass type(a) Start looking for the base class of .

If the search chain cannot get the attribute , Throw out AttributeError abnormal .

One 、__getattr__ Method
This method is called when the property of the object does not exist . If object attributes can be found through normal mechanisms , Not invoke getattr Method .

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

Two 、__getattribute__ Method
This method will be called unconditionally . Whether the attribute exists or not . If... Is also defined in the class getattr , Will not call getattr__() Method , Except in __getattribute Method __getattr__() Or throw it 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)

So in general , In order to retain getattr The role of ,__getattribute__() Method usually returns the method with the same name of the parent class :

def __getattribute__(self, item):
return object.__getattribute__(self, item)

Using methods of base classes to get properties can avoid infinite recursion in methods .

3、 ... and 、__get__ Method
This method is relatively simple , It has little to do with the previous .

If a class is defined __get__(), __set__() or __delete__() Any method in . The object of this class is called a descriptor .

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 # Not invoke __get__
a.x # call __get__

If the property to be searched is in the descriptor object , This descriptor will override the property access mechanism mentioned above , This is reflected in the difference in the search chain , The wording will be slightly different due to different calls :

  • If the call is an object instance ( How to call in the title ),a.x Then it is converted to call :.type(a).__dict__['x'].__get__(a, type(a))
  • If you call a class attribute , A.x Convert to :A.__dict__['x'].__get__(None, A)
  • Other information can be found in the reference document at the end of the text

Four 、__getitem__ Method

This call is also an unconditional call , With this getattribute Agreement . The difference lies in getitem Allow class instances [] operation , It can be understood in this way :

  • __getattribute__ For all . Operator ;

  • __getitem__ For all [] Operator .

    class A(object): a = 1

    def __getitem__(self, item):
    print('__getitem__ call')
    return item
    

    t = A() print(t['a']) print(t['b'])

If you just want the object to be able to pass [] Getting object properties can be simple :

def __getitem(self, item):
return object.__getattribute__(self, item)

summary
When these methods appear at the same time, it may disturb you . I saw a good example on the Internet , A little change :

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'])

It can be understood slowly in combination with the output , Inheritance is not involved here . All in all , Each with __get Methods prefixed with are hooks for getting internal data of objects , The names are different , There are also great differences in use , Only understand them in practice , To really master their usage .

The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved