如何获取导入的类子例程来识别全局变量?

时间:2018-01-29 14:45:04

标签: python python-3.x

如果只是将导入的类名称传递给目标类,如class TargetClass(ImportedClass):,则导入的代码将无法使用已声明的全局变量。 这意味着他们无法与自己的实例进行交互。

代码

from file import Class
class c(Class):
    def sub1(z):
        print(2)

    def sub3(z):
        instance.sub1() #works
        z.sub1()        #works too

instance = c()
Global = 3
instance.sub2() #can't interact with its own instance, raises an error
instance.sub3() #does not raise an error, as sub3 isn't imported
instance.sub4() #raises a NameError

file.py(与第一个代码保存在同一个文件中)

###Class in a different file###
class Class():
    def sub2(z):
        instance.sub1() #will not work
        z.sub1()        #works
    def sub4(z):
        print(Global)

我想要的是能够导入一个类并使用它的子例程,就好像它们已经在类中一样。 这样做的原因是我有一个很长的程序,我希望有一些我不需要开发的子程序保存在不同的文件中。在人们开始建议不同的IDE等之前,我不能使用任何非香草。

1 个答案:

答案 0 :(得分:3)

  

如果您只是将导入的类名称传递给目标类,例如class TargetClass(ImportedClass):

这不是"传递导入的类",这使得TargetClass ImportedClass继承

  

导入的代码无法使用已声明的全局变量。

没有"全局变量"在Python中,意思是"变量,它们在某个地方被声明,然后在每个模块中的任何地方都可以访问。"每个模块都有自己的范围。充其量,变量可以全局到模块,但从不是程序的全局变量。如果某个名称未在模块内明确import或已定义,则该名称不存在。

  

这意味着他们无法与自己的实例进行互动。

问题在于,您并未尝试与自己的实例进行互动,而是在尝试与模块中不存在的名称进行交互。

  

...子程序......

Python没有子程序,它有功能。

这些区别中的一些可能看起来像挑剔,但它们非常重要,在您的情况下,这一切都会增加一些非常糟糕的意大利面条代码,这些代码根本不容易修复。您需要开始使用正确的OOP实践,并停止向上游游泳,以解决您为自己创建的问题。这是一个广泛的主题,所以这里只是一些指示:

  • 除非您使用import导入某些内容或已在模块中声明了该内容,否则它不存在且您无法使用它。
  • 绝不以任何方式依赖全局。
  • 如果您import某事,可以按原样使用。任何无法导入且仅在运行时可用的内容都必须作为函数参数传递。
  • 实例方法的第一个参数名为self。就这么做。
  • 类的依赖关系作为参数传递给__init__

从你的班级中删除明显的废话,只留下有些理智的代码,你仍然有依赖性问题:

class Class():
    def sub2(self):
        self.sub1()  # sub1 is not defined here, cannot be relied upon

    def sub4(self):
        print(Global)  # not defined in module, clear error

from file import Class

class c(Class):
    def sub1(self):
        print(2)

    def sub3(self):
        self.sub1()  # defined above, safe call

如何正确执行此操作的示例:

class Foo:
    def __init__(self, bar):
        self.bar = bar  # don't use globals, pass values to the constructor

    def test(self):
        print(self.bar)  # refers to value defined in __init__, safe

    def test2(self):
        self.test()  # refers to method defined above

注意:此处提到的所有内容都在同一文件中的某处明确定义。这甚至包括self,它作为参数显式传递给每个方法。唯一的"外部"变量是构造函数中的bar;那就是创建了与其他模块/类接缝的地方。

from foo import Foo  # makes Foo available in this module

class Baz(Foo):
    def toast(self):
        self.test2()  # defined in Foo, which we're inheriting from


b = Baz(42)  # passes a value across scope boundaries into Foo
b.toast()  # calls defined method, which calls defined method,
           # which calls defined method, which uses defined value