Kent Johnson wrote:
On Wed, Aug 26, 2009 at 12:25 PM, Mac Ryan<[email protected]> wrote:
Hello everybody,

       I am using "storm" (https://storm.canonical.com/) to manage my
database. In storm, relationships between tables (each table is
represented by a class) are expressed like this (line #4):

1 >>> class Employee(Person):
2 ...     __storm_table__ =employee"
3 ...     company_id =nt()
4 ...     company =eference(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).

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).

The body of a class definition is executed when it is encountered. The
result is a class object (an instance of 'type', usually). Any names
defined at class scope become attributes of the class. The class name
becomes a reference to the class object.

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()

Yes, functions are different than classes. The body of a function is
not executed until it is called.

Note that class methods behave like functions (well, they are
functions) - they are not executed until called. But statements at
class scope are executed to create the class.
I would also be interested in knowing if there is a way around this or
if I simply have to live with it.

You have to live with it unless you can put the attributes inside a
method. In this case, I don't think that will work.

Kent

In Python, you don't declare classes, you define them.

You can forward reference inside a definition (or method), but not elsewhere. That's because it's a one-pass system, where the lines are executed in order. In the case of a "def", execution consists of compiling the body and making a function object. That function object may forward reference all it likes, as long as it's not called until those references are available.

So there are two workarounds to get what you'd like. Your problem is that you want the classes in a certain order, but that the first class has class attributes that have a forward reference. You can't do that directly.

1) As Kent suggested, you can put the attribute initialization inside a "dummy class method," one that will only be executed once, and that you promise will be executed before any other method of the class. Then when you have finished defining the dependency (the other class), you call this dummy method.


Since you don't define all the other stuff, I have to simplify your case. Give a working fragment, if this is too simplified.

class Employee(object):
  __storm_table__ = "employee"
  company_id = []
  company = Company.id         #where Company is a forward reference

class Company:
   id = 42


This gives an error trying to define the Employee.company attribute. So define a classmethod to finish the job, and invoke it later

class Employee(object):
   @classmethod
   def finish(cls):
       cls.__storm_table__ = "employee"
       cls.company_id = []
cls.company = Company.id #where Company is a forward reference del cls.finish #remove this method so it won't be called a second time

class Company:
   id = 42

Employee.finish()   #This finishes initializing the class


help(Employee)
print Employee.company_id

2) Simpler: Simply define the forward referencing class method later in the file, in the same place you would have invoked finish().

class Employee(object):
       __storm_table__ = "employee"
       company_id = []
       #company = Company.id         #Do this later

class Company:
   id = 42

Employee.company_id = Company.id


DaveA
_______________________________________________
Tutor maillist  -  [email protected]
http://mail.python.org/mailman/listinfo/tutor

Reply via email to