【问题标题】:Not able to access object in python while creating object of other class defined in some other file在创建其他文件中定义的其他类的对象时无法访问python中的对象
【发布时间】:2015-04-16 13:28:48
【问题描述】:

我有一个这样的目录结构:

home/
    main.py

    lib/
       mylib/
            Textfile_Class.py
            Excelfile_Class.py
            globals.py   (has all the global variables declared here)
            functions.py

我在main.py 中使用创建了Textfile_class 的对象 txt = TEXT(file).

现在,我想在创建Excelfile_Class 的对象期间使用此变量txt 进行一些操作(例如,如果txt 对象中的变量值为5,则在Excelfile_Class ) 中执行某些操作

Excelfile_Class 中,我还导入了所有全局变量。字符串变量可以在那里访问,但我不知道为什么这个对象txt 在那里无法访问。无论我在Excelfile_Class(self.line_count = txt.count) 中引用txt,我都会遇到以下错误:AttributeError: 'NoneType' object has no attribute 'count'

请帮助我了解为什么会发生这种情况,即使我已经在一个单独的文件中定义了所有变量并在所有文件中导入了这些变量。

例如: main.py

path = os.path.abspath('./lib')
sys.path.insert(0, path)

from mylib.Textfile_class import * 
from mylib.Excelfile_Class import *
from mylib.globals import *
from mylib.functions import *

if __name__ == "__main__":   
    txt = TEXT(file)
    xcel = EXCEL(file)

例如 globals.py

global txt, xcel
txt=None
xcel=None

例如 Textfile_class.py

from globals import *
class TEXT:
    def __init__(self, filename):
        self.count = 0
        with open(filename) as fp:
            for line in fp:
                self.count = self.count + 1`

如 Excelfile_Class.py

from globals import *

class EXCEL:
    def __init__(self, filename):
        self.line_count = 0
        self.operation(filename)

    def operation(self, file):
        self.line_count = txt.count 
        if self.line_count:
            self.some_operation()
        else:
            self.other_operation()

【问题讨论】:

  • 你能提供一个short, self-contained, correct example吗?否则我们能做的最好的就是猜测正确的答案。我确实知道的一件事是,在Excelfile_Class 中,当您使用txt 时,它是None,而不是您所期望的。这就是为什么你会收到AttributeError
  • @WayneWerner 我提供了我的代码的一个小版本,现在请帮忙​​。
  • 考虑到字符串“no_of_lines_in_file”没有出现在您发布的代码中的任何位置,很难确定该错误来自何处以及它的含义......
  • @twalberg 更正了问题。

标签: python class python-2.7 object python-import


【解决方案1】:

当您在函数中为变量名赋值时,您不再使用该变量的全局版本,而是拥有一个全新的变量。

您必须在函数内部使用global关键字来表明您正在使用全局变量。

来自 Python 文档常见问题解答

Python中局部变量和全局变量的规则是什么?

在 Python 中,仅在函数内部引用的变量是隐式全局的。如果一个变量在函数体内的任何地方都被赋予了一个新值,那么它就被认为是一个局部变量。如果一个变量在函数内部被赋予了一个新值,这个变量是隐式本地的,你需要将它显式声明为“全局”。

Read more...

例子:

x = None                # x is momdule-level global variable

def local():
    x = 5               # assign 5 to x, here x is a new variable, global x is not affected.

def glob():
    global x            # indicate we'll working with the global x.
    x = 5               # this affect the global variable.

def print_global():
    print(x)            # Just print the global variable.

local()                 
print_global()          # Prints None
glob()
print_global()          # Prints 5

因此,每次您在函数中引用 txt 时,您都必须告知上下文您将使用 txt 的全局版本。

可能会发生其他事情!

Python 被解释,这意味着它会逐行执行代码,如果在其他模块中(不是在主模块中),您有代码在分配某个值之前尝试访问 txt

if __name__ == "__main__":   
    txt = TEXT(file)

,那么你会得到同样的错误。

推荐:

尽量避免使用全局变量,你已经知道这不是一个好习惯,它会导致代码不稳定。

如果您的问题是您希望txtxcel 随时随地可用,您可以使用模式Singleton (警告,Singleton 被认为是反模式ref )

我会为你发布一个例子,但在我鼓励你重新设计你的程序之前,我保证这将是一个很好的练习!

单例示例:(同样这是一种反模式,但我更喜欢裸全局变量)。

class Globals(object):

    __instance = None

    def __init__(self):

        class wrapped_class:
            def __init__(self):
                self.txt = None
                self.excel = None

        if (Globals.__instance is None):
            Globals.__instance = wrapped_class()

    def __getattr__(self, attrname):
        return getattr(self.__instance, attrname)

    def __setattr__(self, attrname, value):
        setattr(self.__instance, attrname, value)

glob = Globals()            # Since __instance is None this will instantiate wrapped_class and save the reference in __instance
glob.txt = "Txt example"    # Modify the txt attribute of __instance. 
glob_1 = Globals()          # Since __instance is not None it stays as it is.

print(glob.txt)             # Prints  "Txt example"
print(glob_1.txt)           # Prints  "Txt example"

【讨论】:

  • 我按照您的建议对全局进行了更改,但仍然无法正常工作。并且没有您在下面标题“可能发生其他事情!”下提到的这种情况。您能提供进一步的帮助吗?
【解决方案2】:

如果没有代码或堆栈跟踪,很难判断问题出在哪里,但我强烈建议您阅读一些有关 Python 最佳实践、全局变量使用和命名约定的文档。这本身可能会解决您的问题。 命名约定可能听起来很傻,但这些东西和其他与语法相关的选择在 python 中确实很重要。

此外,您的模块中似乎缺少 __init__.py 文件,这取决于您使用的 python 版本,这可能重要也可能不重要。

以下是一些帮助您入门的链接:

【讨论】:

    【解决方案3】:

    我不知道为什么会这样。如果有人知道,他们可以告诉。

    当我使用Using global variables between files in Python中给出的方法时,问题得到了解决。

    所以,最后我把所有的全局变量放在globals.py 的一个函数中,并在main.py 中实例化一次。然后,我使用了from mylib import globals,并将类中的全局变量引用为globals.txt,效果很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 1970-01-01
      • 1970-01-01
      • 2018-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多