0

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

IE

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

4 回答 4

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

第三种选择:继承

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

class bar(foo):
    pass

第四个选项:外部类

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

第五种选择:组合

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()
于 2013-06-20T21:47:09.687 回答
1

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

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

由于 Python 是鸭子类型的,因此可以使用任何对象来保存此配置;它可以是类的实例或类本身。当在运行时指定数据时,前者很方便。后者很方便,因为它允许程序员在编码时使用继承来定义各种属性包。这里的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(等等)来访问数据。

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

您也可以只使用字典来存储要在各个地方访问的数据,但我认为继承和属性访问语法的好处是使用类进行此操作的一个很好的论据。

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

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

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

于 2013-06-20T21:52:15.823 回答
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),然后允许您根据需要添加。如果您有兴趣,这里是关于 super 的文档。

于 2013-06-20T21:29:08.940 回答
0

我不确定您所说的“施工期间干净”是什么意思

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

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

只要您需要变量,在其他类中或任何地方,只需调用 Ax

于 2013-06-20T21:41:07.000 回答