Python dynamic attribute creation

Stephen Hansen me+list/python at ixokai.io
Thu Jul 1 12:51:27 EDT 2010


On 7/1/10 8:46 AM, WANG Cong wrote:
> However, I think setattr() is a builtin function, using it exposes the
> *magic* of metaprogramming (or class-programming, if more correct) at a
> first glance.

I'm going to try this one more time -- you place a great deal of 
importance and special properties on Classes and what they mean to 
object oriented programming. That is perfectly fine.

In some languages, there is indeed a great deal of importance to 
Classes. They define a sort of formal structure, a contract, and the 
rules by which the program runs. Object Oriented Programming is 
ingrained in them as not just a means, but an end -- it's the Right Way 
to do things, the tenants of the OOP paradigm are ingrained as the rules 
of interaction between things.

In these languages, modifying a class at runtime might indeed be 
strange, interesting, magical.

In Python, none of this holds true.

Python's classes are *created* at runtime. The 'class body' is 
executable code which is run when your program starts, the result of 
which is your class.

Now, let me ask you a (rhetorical) question: exactly when are the 
attributes 'created' on a class? You say that adding attributes to an 
object is special, magical.

Consider this relatively simple class:

     class Person(object):
         def __init__(self, name, age=21):
             self.name = name
             self.age = age

I can instantiate that easily, of course:

     me = Person("Stephen", 29)

This is all the normal, basic way we deal with classes and attributes 
right? Right.

Here's the important detail. When __init__ is called, the person object 
has no attributes(*). None at all. Unlike in other more real OOP 
languages where they have attributes which are just basically 
uninitialized, here it has none.

In the __init__, its adding attributes to that object which already 
exists on the fly-- at runtime. Now, here I do something "magic":

     me.hair_color = "brown"

I've now added a new attribute to the existing instance, what you're 
calling something special called "class programming". The problem: 
that's the *exact same syntax* which was used in __init__.

There's no difference between what happened in __init__, where we 
normally consider that we're defining our attributes, and what may 
happen later when you decide to add an attribute 'ont he fly'.

The second case is special *only* if you *imagine* it is-- and it is 
special then *only* in your own mind. It is special, "adding an 
attribute to a previously defined class", if you decide for yourself, 
classes are things that are set in stone or pre-defined in some way.

Classes aren't pre-defined, they're entirely created and defined on the 
fly. That a certain 'on the fly' may happen early (right after you 
create an instance) or another may happen at any point later-- Python 
doesn't and can't even tell the difference (not by itself without any 
jumping through hoops at least).

It's all the same. There's nothing magical about it. Except to you, 
*personally*. In your head, only. Its fine to believe that and treat 
classes as special for you: but its your *choice* to do so.

If you want magic, go learn about metaclasses, descriptors, and such.

Othewrise, I give up.

-- 

    ... Stephen Hansen
    ... Also: Ixokai
    ... Mail: me+list/python (AT) ixokai (DOT) io
    ... Blog: http://meh.ixokai.io/




More information about the Python-list mailing list