python中的全球变量

时间:2013-06-20 21:26:18

标签: python global

我目前有一些类foo(),其中包含一些变量,这些变量不仅在foo类的所有实例之间共享,而且还由其他类bar共享。

class foo():
    __init__(self, a, b):
        self.a = a
        self.b = b

class bar():
    __init__(self, a, b):
        self.a = a
        self.b = b

一种解决方案是制作a和b类变量,但如何在构造过程中干净利落地做?我可以将两个类放在同一个文件中,让它们引用一些全局变量a和b吗?这是不好的做法吗?

4 个答案:

答案 0 :(得分:6)

由于您没有提供您的意图或实际情况,我将提供一些共享变量访问的方法。

第一个选项:全球。

a=b=None

class foo():
    def __init__(self, _a, _b):
        global a, b
        a, b = _a, _b

class bar():
    def __init__(self, _a, _b):
        global a, b
        a, b = _a, _b

第二个选项:foo的班级大战

class foo():
    a = b = None
    def __init__(self, a, b):
        foo.a, foo.b = a, b

class bar():
    def __init__(self, a, b):
        foo.a, foo.b = a, b

第3个选项:继承

class foo():
    def __init__(self, a, b):
        self.a, self.b = a, b

class bar(foo):
    pass

第4个选项:外类

class outer():
    a = b = None
    class foo():
        def __init__(self, a, b):
            outer.a, outer.b = a, b

    class bar():
        def __init__(self, a, b):
            outer.a, outer.b = a, b

第五个选项:compsition

class foo():
    def __init__(self, a, b):
        self.a, self.b = a, b

class bar():
    def __init__(self, a, b):
        self.foo = foo(a,b)

第6个选项:关闭外部函数局部变量

def outer():
    a = b = None
    class foo():
        def __init__(self, _a, _b):
            nonlocal a, b
            a, b = _a, _b

    class bar():
        def __init__(self, _a, _b):
            nonlocal a, b
            a, b = _a, _b

    ... #things with foo and bar

第7个选项:关闭foo的__init__局部变量。

class foo():
    def __init__(self, a, b):
        self.a, self.b = a, b
        class bar():
            nonlocal a, b
            #do things with a and b directly

        self.bar = bar()

答案 1 :(得分:1)

你可以这样做:

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class Bar(Foo):
    pass

通过继承Foo,您将采用Foo的构造方法,因此它将采用相同的方式。如果您需要覆盖它,可以在Bar中以这种方式进行设置:

def __init__(self, a, b, c):
    super(Bar, self).__init__(a, b)
    self.c = c

super将首先调用您的基类'方法(在本例中为Foo),然后允许您添加,如果您愿意。 Here's the documentation on super,如果您有兴趣的话。

答案 2 :(得分:1)

通常的解决方案是创建一个存储共享信息的对象,然后在实例化需要它的类时传递它。通常这是某种配置信息,因此我们将调用类Config

class Config(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    # default values
    number = 0
    text   = "Nothing"

由于Python是duck-typed,因此可以使用任何对象来保存此配置;它可以是类的实例或类本身。在运行时指定数据时,前者很方便。后者可以很方便,因为它允许程序员在编码时使用继承来定义各种属性包。这里的Config类允许您使用它:可以实例化它,使用共享值传递关键字参数,也可以将其子类化,将共享值作为类属性提供。

FooBar类中,您只需接受构造函数中的共享数据:

# these classes both need certain pieces of data
# but are not related by inheritance

class Foo(object):
    def __init__(self, shared):
        self.shared = shared

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

然后你可以实例化Config类,或者定义一个子类,并将结果对象传递给新对象:

# use an instance
adams_config = Config(text="Don't Panic", number=42)
foo1, bar1 = Foo(adams_config), Bar(adams_config)

# use a subclass
class LincolnConfig(Config):
    number = 87 
    text   = "Four score and seven years ago"
foo2, bar2 = Foo(LincolnConfig), Bar(LincolnConfig)

现在,FooBar类的方法可以获取self.shared.numberself.config.text(等等)来访问数据。

由于各种类的实例都持有对同一对象的引用,因此对例如任何具有对这些对象之一的引用的类的任何实例都可以看到adams_configLincolnConfig。如果这不是您想要的行为,您可以在实例化时将想要“冻结”的数据拖出配置对象,并将其设置为实例的属性。

你也可以只使用一个字典来获取你想在不同地方访问的数据,但我认为继承和属性访问语法的好处是用类来实现它的好理由。

您甚至可以拥有一个用作默认值的全局配置对象,因此如果您希望“只是工作”,则无需显式指定它。在这里,我们只使用Config类本身,因为它已经具有我们感兴趣的属性的默认值:

class Baz(object):
    def __init__(self, config=Config):
        self.config = config

通过使用此方法而不是全局变量,您可以更轻松地使用对象的客户端拥有大量具有不同设置的实例,而不是仅限于所有实例的一个“捆绑”设置

答案 3 :(得分:0)

我不确定你在“施工期间干净利落”的意思

您可以通过在函数外定义类变量来使用类变量,如:

class A:
  x = 1
  def __init__(self):
     pass

只要你需要变量,在其他类或任何地方

,只需调用A.x.