Создать статические экземпляры класса внутри указанного класса в Python - PullRequest
12 голосов
/ 30 марта 2010

Извиняюсь, если у меня здесь неправильная терминология - я не могу думать, как бы назвали эту конкретную идиому.

Я пытался создать класс Python 3, который статически объявляет экземпляры себя внутри себя - вроде как enum будет работать. Вот упрощенная версия кода, который я написал:

class Test:
    A = Test("A")
    B = Test("B")

    def __init__(self, value):
        self.value = value

    def __str__(self):
       return "Test: " + self.value

print(str(Test.A))
print(str(Test.B))

При написании этого я получил исключение в строке 2 (A = Test("A")). Я предполагаю, что строка 3 также будет ошибкой, если она зашла так далеко. Использование __class__ вместо Test приводит к той же ошибке.

  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in Test
NameError: name 'Test' is not defined

Есть ли способ сослаться на текущий класс в статическом контексте в Python? Я мог бы объявить эти конкретные переменные вне класса или в отдельном классе, но для ясности, я бы предпочел не делать этого, если смогу помочь.

Чтобы лучше продемонстрировать, что я пытаюсь сделать, вот тот же пример на Java:

public class Test {
    private static final Test A = new Test("A");
    private static final Test B = new Test("B");

    private final String value;

    public Test(String value) {
        this.value = value;
    }

    public String toString() {
        return "Test: " + value;
    }

    public static void main(String[] args) {
        System.out.println(A);
        System.out.println(B);
    }
}

Это работает так, как вы ожидаете: печатает:

Test: A
Test: B

Как я могу сделать то же самое в Python?

Ответы [ 3 ]

12 голосов
/ 30 марта 2010

После того, как вы определили класс, просто добавьте эти две строки:

Test.A = Test("A")
Test.B = Test("B")

Класс в Python - это объект, подобный любому другому, и вы можете добавлять новые переменные в любое время. Вы просто не можете сделать это внутри класса, так как он не определен в это время (он будет добавлен в таблицу символов только после того, как весь код для класса был правильно проанализирован).

3 голосов
/ 30 марта 2010

Хотя ответ Аарона является предпочтительным способом, вы также можете использовать метаклассы:

>>> class TestMeta(type):
...  def __init__(cls, name, bases, dct):
...   cls.A = cls()
...   cls.B = cls()
... 
>>> class Test:
...   __metaclass__ = TestMeta
... 
>>> Test
<class __main__.Test at 0x7f70f8799770>
>>> Test.A
<__main__.Test object at 0x7f70f86f2e10>
>>> Test.B
<__main__.Test object at 0x7f70f86f2e90>
>>> 
2 голосов
/ 30 марта 2010

В Python блок class - это не просто объявление; он выполняется во время выполнения для создания класса. Каждый def внутри класса создает функцию и привязывает имя к пространству имен класса. По этой причине вы не можете просто сделать A = MyClass() непосредственно внутри блока класса, потому что MyClass() не определен полностью, пока блок класса не закроется. Вот как это сделать:

class Test:
    def __init__(self, value):
        self.value = value

    def __str__(self):
       return "Test: " + self.value

Test.A = Test("A")
Test.B = Test("B")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...