cafepy.com

Python Attributes and Methods

Abstract

Explains the mechanics of attribute access for new-style Python objects:

  • how functions become methods
  • how descriptors and properties work
  • method resolution order for classes

Read The Book

Related

This book is part of a series:

  1. Python Types and Objects

  2. Python Attributes and Methods [you are here]

Comments

01 Jun, 2005
Kevin Whitefoot:

Brilliant. Thank you very much for the clearest exposition of Python's type system I have seen.

23 Jul, 2005
Jeronimo Albi:

Yes, very well explained. It's a plesure to read articles like this one. By the way, I really like cafepy site design =).

06 Sep, 2005
Don Bora:

How does one start a new discussion ? I want to start a discuss between PHP and Python , which is better ?

06 Sep, 2005
Don Bora:

Okay i figured it out. Must be tired tonight. :(

17 Jan, 2006
Anonymous*:

Is there a large python discussion board / community out there somewhere?

18 Jan, 2006
Anonymous*:

http://groups.google.com/group/comp.lang.python

22 Feb, 2006
Anonymous*:

This is excellent.

I got particularly intersted at SpecialType. It would be interstesting to have the distinction between 'type(list)' ('list' is given in the library doc as a builtin function) and types.ListType made clear.

It seems that 'list' is, in fact, a class or type name and, when called becomes an instance constructor.

Colin W.

22 Feb, 2006
Shalabh Chaturvedi:

Any 'class or type name' when called returns the instance - in fact that is the standard way of creating an instance in Python - call the class name. This is true for built-in types as well as classes you define. The built-in list used to be a function but version 2.2 onward it is a type. Interestingly the behavior seems same as before when you use it to convert something to a list. But technically you are instantiating a list object rather than calling a function.

Also, list and types.ListType are one and the same object. In fact you can check in Python yourself::

import types types.ListType is list True

When you say type(list), you get the metaclass <type 'type'>. See http://cafepy.com/article/python_types_and_objects/ch03.html (Python Objects Map), which shows both list (shown as <type 'list'>) and <type 'type'>.

08 Dec, 2006
Anonymous*:

Thank you very much for these guides. They've answered virtually all of my questions regarding objects and types the standard documentation didn't answer - and there were a lot of those.

06 Oct, 2007
Anonymous*:

You've written that when retrieving an attribute from an object (print objectname.attrname) the first step performed by Python is to check whether attrname is a Python-provided attribute for objectname and if it is - return it. How exactly is this step performed? Also, I've looked for a good guide explaining what is found in object and what the dictproxy object is, and have found nothing - could you refer me to such a guide?

Thanks in advance!

19 Jan, 2010
V. Argenta*:

Excellent reading about python specificities! I just would say that chapter 2 could be a little more detaild; I had some difficulty reading it. But nothing very serious - all your material is very readable, and you certainly helped me alot. Thanks!

19 Aug, 2010
AkiRoss*:

I think there is an error (or maybe something changed?): in example 1.4, you say:

cobj.dict['d'] = "try to force a value" # Forcing value x = cobj.d # Futile: get is called instead

but some line above you say that resolution order proceed first with instance cobj.dict, then in the type cobj.class.dict

But overriding the class value ( d = Desc() ) with an instance value ( d = [HTML_REMOVED] ) the evaluation order changes. So the x = cobj.d will return the string.

I just tried this with Python 2.6.4:

>>> class Desc(object):
...   def __get__(self, obj, cls=None):
...     return "Desc Get"
>>> class O(object):
...   de = Desc()
>>> o = O()
>>> o.de
'Desc Get' # As expected
>>> o.__dict__['de'] = "A string"
>>> o.de
'A string' # Resolution order changes

Probably everyone noted this, but was just a fix.

Good article anyway, I love to read about the internals :)

~Aki

19 Aug, 2010
AkiRoss*:

Ooops, sorry, forgot about _ set _ . My last comment is wrong, sorry again. ~Aki

20 Apr, 2011
Alicante Airport*:

Your insight view is usefule for me. Thanks!

18 Oct, 2011
bpin*:

In the "who's next class" section, Both B, C are super classes of D, but in the implementation of the do_your_stuff() and find_next_class method D will only invoke either B or C's do_your_stuff not both. Is it just for illustration purpose

12 Jan, 2012
Anonymous*:

Example 1.7 currently does not work as the hidden variable called b does not exist for a first get. To fix it, you need to set b inside init as in

http://docs.python.org/library/functions.html#property

Otherwise, the first get fails. Also, setting seems to just set, and therefore, delete the descriptor from the instance.

Thank you.

21 Jan, 2012
abki_*:

Could you rephrase this part :

«Check objectname.dict for attrname, and return if found. If objectname is a class, search its bases too. If it is a class and a descriptor exists in it or its bases, return the descriptor result.»

The way I understand it is that:

getattirubte looks in object.dict and returns whatever it finds there. If it did not find something it looks inside class bases for a descriptor and returns?

I'm not sure whether getattribute looks for a non-datadescriptor inside the dict of bases or it's looking for a descriptor...

Thanks

08 Jan, 2013
Nick*:

I'm a college student working on a Python interpreter project, and the section on descriptors ("The Dynamic __dict__") saved my life! I couldn't find this level of detail anywhere in the documentation. Thank you so much for providing this.

There are a couple of points I have noticed by experimentation (with Python 3.2) that you might want to clarify:

  1. A descriptor with either __set__ or __delete__ is considered a data descriptor, and can cause an error if the other one is missing. For example:

    >>> class D:
    ...     def __get__(self, obj, cls=None): pass
    ...     def __set__(self, obj, val): pass
    ... 
    >>> class C:
    ...     d = D()
    ... 
    >>> del C().d
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: __delete__
  2. When looking up an attribute, if a non-data descriptor or a non-descriptor is found before a data descriptor in an object's class, it hides any attributes in superclasses. For instance:

    >>> class DD:
    ...     def __get__(self, obj, cls=None):
    ...             print("DD.__get__")
    ...     def __set__(self, obj, val):
    ...             print("DD.__set__")
    ...     def __delete__(self, obj):
    ...             print("DD.__delete__")
    ... 
    >>> class ND:
    ...     def __get__(self, obj, cls=None):
    ...             print("ND.__get__")
    ... 
    >>> class C:
    ...     x = DD()
    ... 
    >>> class D(C):
    ...     x = ND()
    ... 
    >>> D().x
    ND.__get__
  3. Python-provided attributes have descriptors too (although I'm not sure if the implementation actually uses them). These are the slot wrappers and such in object, type, etc. Also, a user-defined class can override a Python-provided attribute. For example:

    >>> class C:
    ...     __dict__ = "__dict__"
    ... 
    >>> c = C()
    >>> c.__dict__
    '__dict__'
19 Sep, 2013
Anonymous*:

Excellent. The following sentence from the python documentation led me to your book: 'Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance’s dictionary.' Your book explained this in crystal clear language, plus a lot more! Great work.

Post Comment
Sign In or provide:
Name*
Email*
Not disclosed
Human Test*
Comment*
Markdown formatting
powered by durusworks