Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the python attribute get and set order?

Python provides us many possibilities on instance/class attribute, for example:

class A(object):
    def __init__(self):
        self.foo = "hello"

a = A()

There are many ways to access/change the value of self.foo:

  1. direct access a.foo
  2. inner dict a.__dict__['foo']
  3. get and set a.__get__ and a.__set__,of course there two are pre-defined methods.
  4. getattribute a.__getattribute__
  5. __getattr__ and __setattr__
  6. maybe more.

While reading source code, I always get lost of what's their ultimate access order? When I use a.foo, how do I know which method/attribute will get called actually?

like image 987
cizixs Avatar asked Jun 21 '15 03:06

cizixs


People also ask

What is get attribute in Python?

Python getattr() The getattr() method returns the value of the named attribute of an object. If not found, it returns the default value provided to the function.

What are the attributes of a class in Python?

Class attributes are the variables defined directly in the class that are shared by all objects of the class. Instance attributes are attributes or properties attached to an instance of a class. Instance attributes are defined in the constructor. Defined directly inside a class.

What is __ Getattr __?

__getattr__ Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self).

How do I get the properties of a class in Python?

Method 1: To get the list of all the attributes, methods along with some inherited magic methods of a class, we use a built-in called dir() . Method 2: Another way of finding a list of attributes is by using the module inspect .


2 Answers

I found out this great post that has a detailed explanation on object/class attribute lookup.

For object attribute lookup:

Assuming Class is the class and instance is an instance of Class, evaluating instance.foobar roughly equates to this:

  • Call the type slot for Class.__getattribute__ (tp_getattro). The default does this:
    • Does Class.__dict__ have a foobar item that is a data descriptor ?
      • If yes, return the result of Class.__dict__['foobar'].__get__(instance, Class).
    • Does instance.__dict__ have a 'foobar' item in it?
      • If yes, return instance.__dict__['foobar'].
    • Does Class.__dict__ have a foobar item that is not a data descriptor [9]?
      • If yes, return the result of Class.__dict__['foobar'].__get__(instance, klass). [6]
  • If the attribute still wasn't found, and there's a Class.__getattr__, call Class.__getattr__('foobar').

There is an illustrated image for this:

enter image description here

Please do check out the original blog if interested which gives a outstanding explanation on python class, attribute lookup, and metaclass.

like image 98
cizixs Avatar answered Oct 05 '22 21:10

cizixs


bar = a.foo...

  1. invokes a.__getattribute__('foo')
  2. which in turn by default looks up a.__dict__['foo']
  3. or invokes foo's .__get__() if defined on A.

The returned value would then be assigned to bar.


a.foo = bar...

  1. invokes a.__getattribute__('foo')
  2. which in turn by default looks up a.__dict__['foo']
  3. or invokes foo's .__set__(bar) if defined on A.
like image 23
Amber Avatar answered Oct 05 '22 19:10

Amber