[Tutor] Declaration order of classes... why it is important?

Alan Gauld alan.gauld at btinternet.com
Thu Aug 27 00:01:34 CEST 2009


"Mac Ryan" <quasipedia at gmail.com> wrote

> 1 >>> class Employee(Person):
> 2 ...     __storm_table__ = "employee"
> 3 ...     company_id = Int()
> 4 ...     company = Reference(company_id, Company.id)
>
> where Company is another class. Now, what I noticed is that Company must
> be declared as a class before Employee, or python will throw an
> exception (Company is not defined).

Thats because you are using Comany as a class attribute rather
than an instance attribute. A class is an object in Python, in the
same sense that functions are objects. Python creates the class
object by evaluating the class definition. Instances are created
by calling the class object.

> I would be interested in understanding why this is so designed. I
> expected that the exception would not be thrown at all, as I imagined
> that the interpreter simply kept track of where classes were declared
> and would try to evaluate the code only once an actual object would be
> instantiated (at that point the interpreter would know where to look for
> each class code).

No it interprets the class definition when it first sees it and the result
is a class object. Because you refer to Company as part of the definition
of a class attribute - part of the class object - Python needs to evaluate
Company to create the class.


> BTW, the behaviour I am describing is exactly what happens with function
> declaration: the following code evaluates as expected, indeed.
>
> def fone():
>  ftwo()
> def ftwo():
>  print "hello"
> fone()
>
> I would also be interested in knowing if there is a way around this or
> if I simply have to live with it.

functions are objects too. But there are no variables inside the
function that persist, even local variables are created then destroyed.
But if you consider a default parameter you do get an error:

def p(a=b):
     a()

def b():
    print 'hello'

p()

Will give a name error and thats as close as I can get to what you
are doing with the class definition using clas variables.

If you use instamnce variables the problem does not exist:

>>> class C:
              d = M
              def __init__(self):
                         pass


Traceback (most recent call last):
  File "<pyshell#131>", line 1, in <module>
    class C:
  File "<pyshell#131>", line 2, in C
    d = M
NameError: name 'M' is not defined

>>> class D:
              def __init__(self):
                        self.d = M


>>>


> It is not that this impede to achieve anything, but in reading code, I
> normally prefer to have the big picture first [This is a house, as you
> see is composed of walls, roof, basement. A wall can have...] while this
> behaviour obliges me to write the code the other way around ["This is a
> brick, if you put together bricks you get a wall, if you put together
> walls you get..."]

You can put the top level function in a separate module and import
the lower level ones, similarly you can put the class definitions in
separate modules. But IMHO its better to just get used to Pythons way
of working. Cut n Paste works wonders :-)

HTH,


-- 
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/ 




More information about the Tutor mailing list