2014-11-06 3519 views
4

(有许多相似和更一般的问题,在通读它们后尝试解决方案,无法让它们工作,因此请在此处询问更具体情况的版本我看到的)Python:全局变量在模块级别是未定义的

我想我真的很想 - 理解Python如何做OOP,因为我的C#/ C++背景更多。所以这就是我现在想要做的。

我从两个模块开始设置我的项目的其余部分,部分是作为理智检查和概念验证。一个模块在我去的时候将东西记录到文件中,同时还存储来自多个模块的数据(最终将它们全部打包并根据请求转储它们)在PyCharm中执行所有这些操作,并提示错误警告,并使用Python 2.7

Module 1: 
    src\helpers\logHelpers.py 
    class LogHelpers: 
     class log: 
     def classEnter(): 
      #doing stuff 
     def __init__(self): 
      self.myLog = LogHelpers.log() #forgot to mention this was here initially 
     [..] various logging functions and variables to summarize what's happening 
    __builtin__.mylogger = LogHelpers 

Module 2: 
    src\ULTs\myULTs.py 
    mylogger.myLog.classEnter() 

(两个模块和根SRC \具有空初始化在他们 .py文件)

所以根据在这个阶段这应该是在这里工作的完全真棒响应(Python - Visibility of global variables in imported modules)但'mylogger'成为'未解决的参考'

所以那是一种方法。我也尝试了更直接的全球性(Python: How to make a cross-module variable?

Module 1: 
    src\helpers\logHelpers.py 
    class LogHelpers: 
     class log: 
     def classEnter(self): 
      #doing stuff 
     def __init__(self): 
      self.myLog = LogHelpers.log() #forgot to mention this was here initially 
     [..] various logging functions and variables to summarize what's happening 
    mylogger = LogHelpers 

    __init__.py 
    __all__ = ['LogHelpers', hexlogger] 
    from .logHelpers import * 

Module 2: 
    src\ULTs\myULTs.py 
    from helpers import mylogger 
    mylogger.myLog.classEnter() 

这个版本得到一个“参数‘自我’空缺”的classEnter,其中各种报告似乎表明错误意味着mylogger是未初始化(误导错误代码,但是这就是它似乎意味着)

然后,我试过这个..

Module 1: 
    src\helpers\logHelpers.py 
    class LogHelpers: 
     class log: 
     def classEnter(self): 
      #doing stuff 
     def __init__(self): 
      self.myLog = LogHelpers.log() #forgot to mention this was here initially 
     [..] various logging functions and variables to summarize what's happening 
    __mylogger = LogHelpers 

    __init__.py 
    __all__ = ['LogHelpers', hexlogger] 
    from .logHelpers import * 

Module 2: 
    src\ULTs\myULTs.py 
    from helpers import mylogger 

    def someFunction(self): 
     global mylogger 
     mylogger.myLog.classEnter() 

这个版本获得误差“全局变量是在模块级未定义”当我将鼠标悬停全球mylogger的。

然后,每个其他模块的想法显然跟踪自己的类的实例,如果我最终不得不我可以使用该方法,并协调他们..但这是一种黑客考虑我是什么试图去做。

这就是我所处的地方,这就是我想要做的事情的要点......我正在尽可能多地阅读类似的问题,但他们都似乎回到了这些(似乎没有工作)或说'不这样做'(这通常是很好的建议,但我并不真正喜欢Pythony的方法来保持多个正在进行的非静态类为大型项目 - 除了将它们全部放在一个目录中)

想法? (如何不好我会重整的Python在这里?)

[编辑]意见的基础上试过,完全消除了内部类迷你版: 好了,做了基于本地的迷你级你说:

class testClass: 
    def __init__(self): 
     self.testVar = 2 
    def incrementVar(self): 
     self.testVar += 1 
myClass = testClass() 

通过init进行设置。PY

__all__ = [myClass] 
from .logHelpers import myClass 

又到其他模块和

from helpers import myClass 
class Test_LogHelpers(unittest.TestCase): 
    def test_mini(self): 
     myClass.incrementVar() 

跑了,而不是直接在原点:(看着PyCharm,没有任何全球.. NameError: name 'myClass is not defined

所以还是(和仍然需要以存储状态)

[编辑]添加回溯:

Traceback (most recent call last): 
    File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module> module = loadSource(a[0]) 
    File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource module = imp.load_source(moduleName, fileName) 
    File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module> from helpers import myClass 
    File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module> 
    __all__ = [myClass] 
NameError: name 'myClass' is not defined 

=============================================== =============================

kk,我知道它与微型工作。我不知道为什么其他方法不行,但这似乎解决了问题。 (参考资料:http://docs.python-guide.org/en/latest/writing/structure/http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html

**logHelpers.py** 
[... some static logging functionality ...] 

class testClass: 
    def __init__(self): 
     self.testVar = 2 

    def incrementVar(self, source): 
     self.testVar += 1 
     mylogger.myLog.info(source + " called, new val: " + str(self.testVar)) 
myClass = testClass() 

**test_LogHelpers_ULT.py** 
import unittest 

from helpers.logHelpers import myClass  

class Test_LogHelpers(unittest.TestCase): 
    def test_mini(self): 
     myClass.incrementVar("LogHelpers") 

出于某种原因跳过 初始化的.py (和保留为空),并打算为明确的进口工作。它也维护状态 - 我创建了测试文件的副本,并且我的日志输出正确地具有“3”用于第一个文件调用帮助器,而“4”用于第二个文件调用帮助器。

感谢Daniel Roseman的帮助和建议,他们让我看起来更朝正确的方向看。如果你能发现为什么以前的东西无法正常工作,只需要增加对我的这种语言的理解就会非常感谢,但我会继续前进,并将你的答案标记为“已回答”,因为它有一些非常有用的反馈。

回答

9

在我开始之前,请注意PyCharm警告并非真正的Python错误:如果您运行代码,您可能会获得更多有用的反馈信息(请记住,像Python这样的动态语言的静态分析只能让您获得更多,直到你真正运行代码才能解决问题)。首先,真的不清楚为什么你在这里有嵌套类。外部类似乎完全没用;你应该删除它。

有关“self”错误消息的原因是您已定义实例方法,该实例方法只能在log的实例上调用。您可以制作mylogger(绝对不需要双下划线前缀)实例:mylogger = log() - 然后导入该实例,或者导入该类并将其实例化到使用位置。

因此,在您的第一个片段中,错误信息非常明确:您尚未定义mylogger。使用我上面的建议,你可以做from helpers import mylogger,然后直接拨打mylogger.classEnter()

最后,我看不到陈述在做什么someFunction。除非您计划将其重新分配到您的范围内,并且将重新分配反映在全球范围内,否则无需声明全球名称。你没有这样做,所以不需要global

顺便说一句,你还应该问你是否需要内部log类。一般来说,类只有在需要在对象中存储某种状态时才有用。在这里,正如你的文档字符串所说的那样,你有一组实用方法。那么为什么要把他们放在一个班级?只需在logHelpers模块中将它们设置为顶层函数(顺便说一下,Python模式更喜欢lower_case_with_underscore模块名称,所以它应该是“log_helpers.py”)。

+0

非常感谢您的反馈 - 我会尽快尝试它(只要我今天晚些时候再次接近代码) 我在保持嵌套类,因为我想从我可以从哪里接触一个单一的联系点扩展到相关但功能不同的不同功能。 (简单的日志记录,现在声明,更晚)。我可以通过拥有各种类和一个具有多个变量的类来完成同样的任务,每个类都存储一个类,只是试图使定义保持内部,因为不应该单独实现类/保持自动完成清理。 – 2014-11-06 16:35:20

+0

当我试图复制我试过的各种东西时,这些额外的__都是一个错误,将它们删除。 – 2014-11-06 16:40:38

+0

那么,请记住嵌套一个类不会给内部类提供对外部类的任何特权访问,所以它很少有任何好处。通常在Python中,嵌套的元素是包和模块,而不是类。 – 2014-11-06 16:52:17