Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must classes be defined in order of appearance in python module?

Let's say I have a python file test.py that looks like this:

class MyFirstClass():
    prop=3

class MySecondClass():
    prop1 = 0.
    prop2 = MyFirstClass()

Then I can run this and it works:

from my_test import MyFirstClass, MySecondClass

obj = MySecondClass()

But if I write my python file like this, just inverting the definition order:

class MySecondClass():
    prop1 = 0.
    prop2 = MyFirstClass()

class MyFirstClass():
    prop=3

then I get an error saying that MyFirstClass is not defined.

So Python obviously expect MyFirstClass to be defined before it is used in MySecondClass.

But I'm just wondering why it is like that. After all, function definitions with def can be made in any order within a module. So I'm (perhaps naively) a bit surprised that class definitions must be made in order like this.

I suspect that this has something to do with the fact that I used MyFirstClass to initialize a class-level attribute of MySecondClass. But could someone clarify what is going on here?

like image 229
Ben Avatar asked Dec 22 '25 13:12

Ben


1 Answers

You are on the right track with your thinking.
The lines of code inside your function aren't executed when you define your function; they're executed when you call your function. The lines of code inside your class definition are executed when you define your class; they have to be, in order to shape the class you are writing.

Here is a snippet showing operations on functions that are more analogous to class definition

def my_function():
    pass

my_function.some_attribute = 'foo'

def another_function():
    pass

# This line won't work if you tried to define my_function after it
another_function.some_function = my_function;

Here is some example code you can run to demonstrate this (tested on python 3.9)

class MyClass:
    print('this code executes at module read time')
    my_attribute = 3

print(f'I can access the MyClass namespace from this line; {MyClass.my_attribute=}')

def my_function():
    print('this code executes when the function is called')
    this_will_raise_a_name_error_when_the_function_runs

print('done with definitions')
my_function()

Functions need their own scope when they run to behave sensibly. Classes don't need their own scope when you define them to be defined sensibly. Further discussion of function scopes can be found here Short description of the scoping rules

like image 144
Grrttgrrtt Avatar answered Dec 24 '25 04:12

Grrttgrrtt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!