Your first example breaks because name my_variable
is not yet defined when the class Meta
statement's body is executed.
You second example won't work either for the same reason (my_variable
is not yet defined when the class ParserScheme
statement's body is executed), and if it was it would still break when executing the class Meta
statement's body because it will be executed as part of the class ParserScheme
statement's body hence before the name ParserScheme
is defined.
What you have to understand here is that class
and def
are executable statements which (if at the top level of a module) are executed sequentially when the module is first imported into the current process. In the case of a class
statement, the statement's body is first sequentially executed in a dedicated namespace then this namespace is passed to the metaclass constructor and used to create the class object's attributes (YourClass.__dict__
).
To make a long story short: in a class
statement body, you just cannot reference names that are not yet defined in the current or enclosing scope. Period.
The obvious solution here would be to define my_variable
before the class statement, but I assume you want it to be more dynamic ? If yes, you'll have to define your class in a function:
def create_parser_class(my_variable):
class ParserScheme(Schema):
class Meta:
result = func(my_variable)
return ParserScheme
my_variable = 42
cls = create_parser_class(my_variable)
my_parser = cls()
But I can't garantee it will work out of the box (nor even work at all FWIW) with Marshmallow (which I never used but probably has some metaclass stuff happening). Also depending on what my_variable
is used for, you may want to make sure you don't have two calls to create_parser_class
with the same value as argument.
As a last note : you perhaps have a XY problem here - that's sometimes the case when someone asks how to do something a bit non-obvious or unusual. Perhaps you should edit your post to explain the "problem behind" - that is, the problem you are actually trying to solve with this "solution".
Oh and yes:
I am rather new to OOP, and I am not sure I understand really well the concept of class attribute
In Python, classes are objects too (instances of their metaclass, by default the type
object), and as such they have their own attributes. Every name you define (with an assignment, a def
statement, a class
statement or an import
statement) at the top-level of the class
statement becomes an attribute of the class object (unless a custom metaclass makes some transformations on the way, that is).
Class attributes are accessible from the instances too (unless shadowed by an eponym instance variable), and are shared between all instances.