简体   繁体   English

如何从 Python 中的变量定义类属性?

[英]How can I define a class attribute from a variable in Python?

I need to access a variable from a nested class.我需要从嵌套类访问变量。 The objective is to create a Schema using the Marshmallow library.目标是使用 Marshmallow 库创建模式。 The code looks like this :代码如下所示:

class ParserScheme(Schema):

    class Meta:
        # Here I meed to access the value of my_variable :
        result = func(my_variable)

my_variable = 'foo'
my_parser = ParserScheme()

If I manage to pass my variable as a class attribute of the outer class (ParserScheme), then it is easy to get it into the inner class (Meta).如果我设法将我的变量作为外部类 (ParserScheme) 的类属性传递,那么很容易将其放入内部类 (Meta) 中。

class ParserScheme(Schema):
    class_attribute = my_variable
    class Meta:
        result = func(ParserScheme.class_attribute)

my_variable = 'foo'
my_parser = ParserScheme()

However I can't seem to find a way to dynamically set a class attribute.但是我似乎找不到动态设置类属性的方法。 And if I set a "classic" attribute (I mean an attribute of instances of the class, not of the class itself), then I can't access it from the inner class.如果我设置了一个“经典”属性(我的意思是类实例的属性,而不是类本身的属性),那么我就无法从内部类访问它。

I also thought of using a global variable, but that does not really quite satisfy me.我也想过使用全局变量,但这并不能真正让我满意。 Is there another way of doing this ?还有另一种方法吗?

I am rather new to OOP, and I am not sure I understand really well the concept of class attribute.我对 OOP 比较陌生,我不确定我是否真的理解类属性的概念。 I fear that there is an easy way to do that but I did not see it as I am to focused on the way I think this should work...我担心有一种简单的方法可以做到这一点,但我并没有像我那样专注于我认为这应该起作用的方式......

Your first example breaks because name my_variable is not yet defined when the class Meta statement's body is executed.您的第一个示例中断,因为在执行class Meta语句的主体my_variable未定义名称my_variable

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.你第二个例子不会为同样的原因无论是工作( my_variable的时候没有定义class ParserScheme执行语句的身体),如果是执行时,它仍然会打破class Meta语句的身体,因为它会作为一部分来执行class ParserScheme语句的主体,因此名称ParserScheme被定义之前。

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.这里你必须理解的是, classdef是可执行语句,当模块第一次导入当前进程时,它们(如果在模块的顶层)按顺序执行。 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__ ).class语句的情况下,语句的主体首先在专用命名空间中顺序执行,然后将此命名空间传递给元类构造函数并用于创建类对象的属性 ( 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.长话短说:在class语句主体中,您不能引用尚未在当前或封闭范围内定义的名称。 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 ?这里显而易见的解决方案是在 class 语句之前定义my_variable ,但我假设您希望它更动态? 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).但是我不能保证它可以与 Marshmallow 一起使用(我从未使用过,但可能会发生一些元类的事情)。 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.此外,根据my_variable的用途,您可能需要确保没有两次调用create_parser_class的值与参数相同。

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.最后一点:您可能在这里遇到了XY 问题-有时当有人问如何做一些不明显或不寻常的事情时就是这种情况。 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我对 OOP 很陌生,我不确定我是否真的理解类属性的概念

In Python, classes are objects too (instances of their metaclass, by default the type object), and as such they have their own attributes.在 Python 中,类也是对象(它们的元类的实例,默认情况下是type对象),因此它们有自己的属性。 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).定义(与分配,一个每名def语句,一class的语句或import语句)在的顶级class除非有自定义元类,使在路上一些转换语句变成类对象的属性(即是)。

Class attributes are accessible from the instances too (unless shadowed by an eponym instance variable), and are shared between all instances.类属性也可以从实例访问(除非被同名实例变量隐藏),并且在所有实例之间共享。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM