简体   繁体   English

在 class 实例中使用模块变量

[英]Using a module variable within a class instance

I have a class which is instantiated many times.我有一个多次实例化的 class。 It requires a certain parameter from a configuration file.它需要配置文件中的某个参数。 I thought of reading the config file once in the module level so that each instance can refer to the loaded parameter.我想在模块级别读取一次配置文件,以便每个实例都可以引用加载的参数。

I'm probably missing something as I'm receiving:我可能在收到以下信息时遗漏了一些东西:
UnboundLocalError: local variable 'the_parameter' referenced before assignment

Here's the outline of the code:这是代码的大纲:

import ConfigParser

config = ConfigParser.ConfigParser()
config.read('config.cfg')
the_parameter = config.getint('my_section','the_parameter')

class MyClass():
    def my_func(self):
        print(the_parameter)

Works for me为我工作

>>> class MyClass( object ):
...     def aFunc( self ):
...         print( some_global )
... 
>>> some_global= 3
>>> x= MyClass()
>>> x.aFunc()
3

The code that's posted has probably had too many details removed to show the real error.发布的代码可能删除了太多细节以显示真正的错误。

Don't try to use global variables in your classes, this is somewhat against the purpose of classes.不要试图在你的类中使用全局变量,这有点违背类的目的。 If your class requires a config object, you could pass it via dependency injection, ie explicitely pass it as an argument to your class:如果您的 class 需要配置 object,您可以通过依赖注入传递它,即将它作为参数显式传递给您的 class:

config = ConfigParser.ConfigParser()
config.read('config.cfg')

class MyClass(object):
    def __init__(self, config):
        self._config = config

    def my_func(self):
        print self._config.getint('my_section', 'the_parameter')

Btw if you really only need the single parameter, you can of course pass the parameter instead of the whole config object.顺便说一句,如果你真的只需要单个参数,你当然可以传递参数而不是整个配置 object。 If you might need other parameters in the future, passing the config object would be the better choice.如果您将来可能需要其他参数,传递配置 object 将是更好的选择。

Put global the_parameter in the function to fix the issue.global the_parameter放入 function 以解决此问题。

S.Lott is right: the OP's code works. S.Lott 是对的:OP 的代码有效。
It works either with the_parameter defined before the class's definition or after, it doesn't matter.它可以与在类定义之前或之后定义的the_parameter一起使用,没关系。

What happens is that when the function my_func is called as a method of one of the instances, the object the_parameter is searched in the environment of the my_func 's code block, that is to say: first in the local scope of the function, then outside the function, until the global namespace (= module level), because "When a name is used in a code block, it is resolved using the nearest enclosing scope." What happens is that when the function my_func is called as a method of one of the instances, the object the_parameter is searched in the environment of the my_func 's code block, that is to say: first in the local scope of the function, then在 function 之外,直到全局命名空间(= 模块级别),因为“当在代码块中使用名称时,它使用最近的封闭 scope 解析。” ( ref ) 参考

So there's no need to find a solution to a problem that doesn't exist.因此,没有必要为不存在的问题找到解决方案。

. .

However, this code can be improved IMO, because, as it is, it implies that the_parameter must be found among all the objects binded at the global level, and these objects are possibly very numerous.但是,IMO 可以改进此代码,因为它实际上意味着必须在全局级别绑定的所有对象中找到the_parameter ,并且这些对象可能非常多。
Defining global the_parameter inside the function's code shortens the process of research: the execution will go directly at the global level to search the object, without exploring the function's namespace.在函数代码中定义global the_parameter缩短了研究过程:执行将 go 直接在全局级别搜索 object,而无需探索函数的命名空间。

But anyway, in these two cases, it is a poor process, contrary to the the purpose of classses, as underlined by jena : an instance must be a self-sufficient object having fields that provide all that is necessary to its functionning.但无论如何,在这两种情况下,这是一个糟糕的过程,与类的目的相反,正如 jena 强调的那样:一个实例必须是一个自给自足的object具有提供其功能所需的所有字段的字段。

. .

The solution of jena isn't the best yet, because it implies that the_parameter must be passed as argument each time an instance will be created. jena 的解决方案还不是最好的,因为它意味着每次创建实例时都必须将 the_parameter作为参数传递。
If the_parameter is intended to be invariably common to all the instances of MyClass , the code should make it a more strictly associated object to all the instances of MyClass .如果_parameter旨在对MyClass的所有实例始终通用,则代码应使其成为与MyClass的所有实例更严格关联的 object。

So it seems to me that the following code is the more convenient:所以在我看来,下面的代码更方便:

class MyClass(object):
    import ConfigParser
    config = ConfigParser.ConfigParser()
    config.read('config.cfg')
    the_parameter = config.getint('my_section','the_parameter')
    del ConfigParser,config  

    def my_func(self):
        print('the_parameter == ' + str(MyClass.the_parameter)) 

Doing so, the search of the_parameter will be done by exploring the namespace of the class, not in the vast global namespace.这样做, the_parameter的搜索将通过探索 class 的命名空间来完成,而不是在广阔的全局命名空间中。

. .

Update更新

Well, I realize that to find MyClass.the_parameter , the execution must first search the object MyClass in the global namespace, and that anihilates what I pretended.好吧,我意识到要找到MyClass.the_parameter ,执行必须首先在全局命名空间中搜索 object MyClass ,这会破坏我的假装。

To avoid the search in the global namespace, the call to the _ class _ attribute of the instance must be done like that:为避免在全局命名空间中搜索,对实例的_class _属性的调用必须按如下方式进行:

def my_func(self):
    print('the_parameter == ' + str(self.__class__.the_parameter)) 

If you don't declare var as global and don't initialize it, accessing value of non-defined variable is error如果您不将 var 声明为全局并且不对其进行初始化,则访问未定义变量的值是错误的

so所以

global the_parameter = config.getint(...)

is the answer是答案

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

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