Классы Python только с одним экземпляром: когда создавать (один) экземпляр класса и когда вместо этого работать с классом?

11

Данный класс Python, который будет создан только один раз, то есть будет только один объект класса. Мне было интересно, в каких случаях имеет смысл создавать отдельный экземпляр класса, а не работать непосредственно с классом.

Есть похожий вопрос , но он имеет другую направленность:

  1. речь идет о группировании глобальных переменных и функций в класс и
  2. Это не специфично для Python. Последнее означает, что оно не учитывает тот факт, что (в Python) классы также являются объектами.

ОБНОВИТЬ:

В Python я могу делать следующее как с классами, так и с объектами:

class A(object):
    pass

A.some_state_var = True
# Then later
A.some_state_var = False


my_a = A()

my_a.some_state_var = True
# Then later
my_a.some_state_var = False

Поэтому я не вижу, как выбор между классом и экземпляром этого класса зависит от состояния (в Python). Я могу поддерживать состояние с любым из двух.

Кроме того, мотивация для создания моего экземпляра класса / класса не сводится к выполнению требования Singleton.

Кроме того, речь идет не столько о создании нового типа.

Мотивация состоит в том, чтобы сгруппировать связанный код и данные и иметь к ним интерфейс. Вот почему я изначально смоделировал его как класс в диаграмме классов. Только когда дело дошло до реализации, я начал задаваться вопросом, создавать ли экземпляр этого класса или нет.

langlauf.io
источник

Ответы:

16

Данный класс Python, который будет создан только один раз, то есть будет только один объект класса. Мне было интересно, в каких случаях имеет смысл создавать отдельный экземпляр класса, а не работать непосредственно с классом.

Так вот это:

class Singleton:
    '''don't bother instantiating me'''
    clsvar1 = 'foo'

    @classmethod
    def foobar(cls, *args, **kwargs):
        if condition():
            cls.clsvar1 = 'bar'

против этого?

class Singleton:
    '''instantiate and use me'''
    def __init__(self):
        self.var1 = 'foo'

    def foobar(self, *args, **kwargs):
        if condition():
            self.var1 = 'bar'

Рекомендация

Я определенно предпочел бы тот, который предназначен для создания экземпляра. Когда вы создаете «тип вещи», это подразумевает, что вы создаете вещи этого типа.

Мотивация состоит в том, чтобы сгруппировать связанный код и данные и иметь к ним интерфейс.

Тем не менее, почему бы просто не использовать модуль, поскольку все, что вам нужно, это пространство имен? Модули - это синглтоны, код и данные, относящиеся к группе, и это немного проще и, вероятно, будет рассматриваться как более Pythonic:

var1 ='foo'

def foobar(*args, **kwargs):
    global var1
    if condition():
        var1 = 'bar'

Таким образом, использование будет вместо:

from modules.singleton import Singleton
Singleton.foobar()

или же

from modules.singleton import Singleton
the_singleton = Singleton()
the_singleton.foobar()

сделай это:

from modules import singleton
singleton.foobar()
Аарон Холл
источник
3
Спасибо за Ваш ответ. Вы бы действительно предложили создать новый модуль (новый .py файл) для каждой функции (включая переменные)? Это может привести ко многим маленьким .py файлам. Или вы бы сгруппировали все (по крайней мере, как-то связанные) «безклассовые» функции и переменные в одном модуле?
langlauf.io
Еще одно замечание: вы пишете «так как все, что вы хотите, это пространство имен». Я хочу сгруппировать связанный код, т.е. функции и данные, в одном месте и иметь интерфейс к нему. Дело не столько в создании «Типа». Во время проектирования это в любом случае привело бы к классу в диаграмме классов, не так ли?
langlauf.io
2

Мне было интересно, в каких случаях имеет смысл создавать отдельный экземпляр класса, а не работать непосредственно с классом.

Это одна из тех вещей, которая вызовет религиозную войну, если вы сильно в нее втянетесь.

Но в целом практика, которую я видел много раз, заключается в том, что методы класса должны заниматься только созданием экземпляров этого класса.

Если вы думаете о том, что такое класс, какова его цель / поведение, тогда это имеет смысл. Целью класса является создание экземпляров объектов, которые основаны на нем . Это план, который также может построить здание. Класс "Пользователь" создает объекты "пользователь". Класс "Dog" создает объекты "собака" и т. Д. И т. Д.

Если это поведение класса, то имеет смысл, что методы, которые вы добавляете в класс «X», будут заниматься созданием объектов «x».

Поэтому, даже если вам когда-либо понадобится только один объект «x», вы все равно должны его создавать.

Добавление в класс X методов, не связанных с созданием экземпляров объектов «x», может привести к путанице в неожиданном коде. Конечно, в реальном мире есть множество примеров, когда люди все равно это делали, но, как я сказал, этот путь ведет к религиозной войне.

Кормак Мулхолл
источник