Как инициализировать атрибуты класса?

В настоящее время у меня есть следующие два способа:

class Venue:
    store = Database.store()
    ids = [vid for vid in store.find(Venue.id, Venue.type == "Y")]

    def __init__(self):
        self.a = 1
        self.b = 2

ИЛИ

class Venue:

    @classmethod
    def set_venue_ids(cls):
        store = Database.store()
        cls.ids = [vid for vid in store.find(Venue.id, Venue.type == "Y")]

    def __init__(self):
        self.a = 1
        self.b = 2

И перед использованием / создание экземпляра класса я бы вызвать:

Venue.set_venue_ids()

Каким был бы правильный путь достижения этого?

Если это первый способ, что бы я сделал, если бы создание экземпляра атрибута требовало более сложной логики, которую можно было бы сделать более просто с помощью функции?

Или есть совершенно другой способ структурировать мой код, чтобы выполнить то, что я пытаюсь сделать?

1 ответ

  1. С чисто технической точки зрения класс является экземпляром своего метакласса, поэтому инициализатор метакласса является очевидным кандидатом на инициализацию атрибутов класса (по крайней мере, когда у вас есть что-то немного сложное).

    Теперь, учитывая каноническое время жизни объекта класса (обычно всего процесса), я бы определенно не использовал атрибут здесь — Если кто-то добавляет или удаляет места из вашей базы данных во время выполнения процесса, ваши idsатрибуты будут выходить из синхронизации. Почему вы не используете classmethodвместо этого, чтобы убедиться, что ваши данные всегда в актуальном состоянии ?

    Ах да, еще один способ построить свой Venue.ids(или любой другой атрибут класса, требующий нетривиального кода) без наличия сложного кода на верхнем уровне класса, загрязняющего пространство имен класса (вы заметили, что в вашем первом примере storeатрибуты класса также становятся атрибутами класса, а также vidпри использовании Python 2.x ?) заключается в том, чтобы поместить код в простую функцию и вызвать эту функцию из тела оператора класса, т. е.:

    def list_venue_ids():
        store = Database.store()
        # I assume `store.find()` returns some iterator (not a `list`)
        # if it does return a list, you could just
        # `return store.find(...)`.    
        return list(store.find(Venue.id, Venue.type == "Y"))
    
    class Venue(object):
        ids = list_venue_ids()
        def __init__(self):
            self.a = 1
            self.b = 2