global_c2 gets an error but local_c2 doesn't. This makes sense because when the compiler looks through this file it won't know that Class2 is going to exist. Also if I switch the class around so that Class2 is defined first it works.

However I was wondering if there is another way to get around this. Maybe I can somehow tell python that Class2 is going to exist so don't worry about it, or do I just have to put them in the right order?

@AshwiniChaudhary It is indented properly. Well, the self argument hints at foo being intended as a method, but it works either way and illustrates the problem just fine either way.
–
delnanSep 30 '12 at 14:05

2 Answers
2

The compiler doesn't do anything here. In both cases, exactly the same bytecode sequence is generated to look up the class at runtime and instanciate it.

What makes the difference is when the statements are run. All code in a Python module is executed top from bottom -- there is no such thing as a declaration, everything's a definition and every binding is dynamic. Code in a class definition is run when the class definition is encountered (and therefore before the second class is brought into existence and bound to the name Class2). Code in a function runs when the function is called, and because you don't call the function before the definition of the second class, it's available by the time you call that function.

That's basically what every solution boils down to: Delay binding until whatever you're binding to exists.

Thanks, this is the explanation I was looking. I was hoping there might be a way of declaring Classes in init files but I assume "there is no such thing as a declaration" means this would be impossible. Thanks
–
PaulSep 30 '12 at 14:14

Actually, you should not take "there is no such thing as a declaration" taht literally - it is true that you don't have to declare variables or types for those, but a class, or even a function body is a declaration for all effects.
–
jsbuenoSep 30 '12 at 14:23

1

Also, the Django framework, when hit by this problem when people would build their relation-oriented object models, opted for this solution: it does allow for a string reference to a class yet-to-be declared (for ex. (attr = "Class2") instead of attr = Class2). Upon using the attribute, if it's type is string, it gets a reference to the actual class that has that name on the module.
–
jsbuenoSep 30 '12 at 14:26

@jsbueno While I keep using that phrasing mostly because it has a nice ring to it, it's completely true. def and class are regular executable statements (and they can also execute several times!), they create a function/class object and store it under a name. Never at any point in time anything declares that there is or will be a class or function under that name, or even that this name will exist. It is true that with straightforward use cases, this looks and feels a lot like declarations (with limitations and no forward declarations) but it's actually an entirely different approach.
–
delnanSep 30 '12 at 14:32

@jsbueno The Django example is very interesting. I suppose they keep the string around and resolve it only when they need to access the class? A serialization framework of mine does something similar, references between model classes are stored as module_name, class_name tuples.
–
delnanSep 30 '12 at 14:35