具有一组恒定属性的Init类实例,这些属性将被初始化一次

时间:2018-10-08 22:09:37

标签: python python-3.x

我想要一个类MyClass的实例,它们共享一些从文件中读取的常量属性,但是还具有该实例唯一的值的属性。但是,我只想为所有实例读取一次文件。

类似

config.json

{
  "a": 1,
  "b": 2,
}

然后定义类:

class MyBaseClass:

    def __new__(cls):
        with open('config.json', 'r') as f:
            for key, value in json.load(f).items():
                setattr(cls, key, value)

class MyClass(MyBaseClass):

    def __init__(self, param):
        self.c = param

当我初始化MyClass的实例时,我想要

inst1 = MyClass("One")
inst2 = MyClass("Two")

使inst1.cOne,而inst2.cTwo。但是我想以某种方式实现这一点,以便MyBaseClass仅从config.json读取数据一次。像是单身。我该怎么办?

2 个答案:

答案 0 :(得分:1)

您已经拥有大部分框架。首次创建类时,有许多代码会运行。最简单使用的是类主体本身。您可以使用它来创建一个类变量,该类变量包含所需的属性,并带有如下所示的代码段:

class MyBaseClass:
    with open('config.json', 'r') as f:
        attributes = json.load(f)

    def __new__(cls):
        self = super().__new__(cls)
        self.__dict__.update(cls.attributes)
类命名空间中的

Any 名称在运行该类后仍保留为类变量,而不仅仅是方法。仅当您拥有不使用插槽或具有冲突属性的常规类时,才可以更新字典。在这种情况下,请在setattr中使用__new__循环。

答案 1 :(得分:1)

您可以将MyBaseClass定义为元类,因此只需完成一次。

>>> class MyBaseClass(type):
...    def __new__(cls, name, bases, dct):
...        x = super().__new__(cls, name, bases, dct)
...        print('In metaclass')
...        with open('config.json', 'r') as f:
...            for key, value in json.load(f).items():
...                setattr(x, key, value)
...        return  x
...
>>>

现在,将MyBaseClass指定为MyClass的元类。

>>> class MyClass(metaclass=MyBaseClass):    
...    def __init__(self, param):
...        self.c = param
...
In metaclass
>>>

定义MyClass时,它将仅调用一次MyBaseClass.__new__方法。现在,

>>> inst1 = MyClass("One")
>>> inst2 = MyClass("Two")

将导致创建两个实例,而不会进一步读取config.json