Написание метода python, который ссылается как на экземпляр, так и на класс

Скажем, у нас есть класс Pet в Python:

class Pet(object):
    num_pets = 0

    def __init__(self, name):
        self.name = name
        Pet.num_pets += 1

    def speak(self):
        print("My name %s and the number of pets is %d" % (self.name, self.num_pets))

Я хочу, чтобы метод init создавал экземпляр, но также обновлял атрибут класса. Есть ли более элегантный способ сделать это, чем код выше? Я попытался передать в self и cls метод init, а затем ссылаться на cls вместо Pet, где num_pets увеличивается, но это не сработало.

Ответ 1

Вы можете использовать classmethod для увеличения количества домашних животных:

class Pet(object):
    num_pets = 0

    def __init__(self, name):
        self.name = name
        self.incr_num_pets()

    @classmethod
    def incr_num_pets(cls):
        cls.num_pets += 1

В качестве альтернативы вы можете увеличивать num_pets на type(self):

def __init__(self, name):
    self.name = name
    type(self).num_pets += 1

хотя я считаю, что этот второй метод будет немного менее изящным, даже если он меньше печатает.

Ответ 2

В вашем случае вы можете использовать __new__ вместе с __init__:

class Pet(object):
    num_pets = 0

    def __new__(cls, *args, **kwargs):
        cls.num_pets += 1
        return object.__new__(cls)

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

Ответ 3

Вы можете получить доступ к собственному классу с помощью self.__class__, это означает, что ваш __init__ может выглядеть так:

def __init__(self, name):
    self.name = name
    self.__class__.num_pets += 1