как загрузить объект (модель) в класс python [duplicate]

Попробуйте следующее:

punct(u(a(t(i(o(n)?)?)?)?)?)?
584
задан hxysayhi 28 June 2017 в 08:30
поделиться

17 ответов

Код на основе Ответ Tolli .

#decorator, modyfies new_cls
def _singleton(new_cls):
    instance = new_cls()                                              #2
    def new(cls):
        if isinstance(instance, cls):                                 #4
            return instance
        else:
            raise TypeError("I can only return instance of {}, caller wanted {}".format(new_cls, cls))
    new_cls.__new__  = new                                            #3
    new_cls.__init__ = lambda self: None                              #5
    return new_cls


#decorator, creates new class
def singleton(cls):
    new_cls = type('singleton({})'.format(cls.__name__), (cls,), {} ) #1
    return _singleton(new_cls)


#metaclass
def meta_singleton(name, bases, attrs):
    new_cls = type(name, bases, attrs)                                #1
    return _singleton(new_cls)

Объяснение:

  1. Создайте новый класс, наследующий от данного cls (it не изменяет cls в случае, если кто-то хочет, например, singleton(list))
  2. Создать экземпляр. Перед переопределением __new__ это так просто.
  3. Теперь, когда у нас есть легко созданный экземпляр, переопределяет __new__ с использованием метода, определенного момента назад.
  4. Функция возвращает instance только в том случае, если это то, что ожидает абонент, в противном случае возникает TypeError. Условие не выполняется, если кто-то пытается наследовать от украшенного класса.
  5. Если __new__() возвращает экземпляр cls, то метод __init__() нового экземпляра будет вызван как __init__(self[, ...]), где self - это новый экземпляр, а остальные аргументы те же, что и в __new__(). instance уже инициализирован, поэтому функция заменяет __init__ функцией, ничего не выполняющей.

Посмотрите, как он работает в сети

393
ответ дан Community 16 August 2018 в 11:34
поделиться
  • 1
    Нет, синглтоны никогда не бывают хорошими. Регистрация может быть хорошим кандидатом на то, чтобы быть глобальным (настолько ужасным, как есть), но, конечно, не singleton. – Cat Plus Plus 23 July 2011 в 12:32
  • 2
    Посмотрите googletesting.blogspot.com/2008/08/… . Это, как правило, анти-синглтон (по уважительной причине), но у него есть хорошее объяснение того, почему неизменяемые синглтоны и синглтоны без побочных эффектов не имеют одинаковых проблем, если вы осторожны. Я собираюсь процитировать его немного в конце моего сообщения. – agf 23 July 2011 в 12:36
  • 3
    Моя проблема с одиночными точками - это глупая предпосылка «только одного экземпляра». Это и тонна проблем безопасности потока. И зависимость скрывается. Глобалы плохие, а синглтоны - просто глобальные проблемы с большим количеством проблем. – Cat Plus Plus 23 July 2011 в 12:46
  • 4
    Хотя это не является ответом на мой вопрос, ресурсы, на которые вы указываете, очень полезны. Я неохотно даю вам +1 – theheadofabroom 25 July 2011 в 14:08
  • 5
    @Cat Очень хорошие применения для одиночных игр. Одним из них является ленивое создание аппаратных модулей (особенно в однопоточных приложениях) (но существуют также потокобезопасные синглтоны). – Paul Manta 6 August 2011 в 14:47
  • 6
    @Alcott __new__ в метаклассе - это когда новый класс class является новым - когда он определен, а не когда instance будет новым. Вызов класса (MyClass()) - это операция, которую вы хотите переопределить, а не определение класса. Если вы действительно хотите понять, как работает Python, самое лучшее, что вы можете сделать (кроме использования его), читается docs.python.org/reference/datamodel.html . Хорошей ссылкой на метаклассы является eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example . Хорошая статья о синглонах - это серия из блога google, которую я связал в этом ответе. – agf 20 September 2011 в 07:28
398
ответ дан Community 6 September 2018 в 05:46
поделиться

Я не могу вспомнить, где я нашел это решение, но я считаю, что это самый «элегантный» из моей не-Python-экспертной точки зрения:

class SomeSingleton(dict):
    __instance__ = None
    def __new__(cls, *args,**kwargs):
        if SomeSingleton.__instance__ is None:
            SomeSingleton.__instance__ = dict.__new__(cls)
        return SomeSingleton.__instance__

    def __init__(self):
        pass

    def some_func(self,arg):
        pass

Почему мне нравится это? Нет декораторов, нет мета-классов, нет множественного наследования ... и если вы решите, что больше не хотите, чтобы это был синглтон, просто удалите метод __new__. Поскольку я новичок в Python (и ООП в целом), я ожидаю, что кто-то задаст мне прямо, почему это ужасный подход?

0
ответ дан 2cynykyl 16 August 2018 в 11:34
поделиться
  • 1
    почему это ужасный подход? , когда вы хотите создать еще один класс singleton, вам нужно скопировать & amp; вставьте __new__. Не повторяйте себя . – GingerPlusPlus 30 December 2014 в 18:56
  • 2
    Кроме того, почему ваш новый принимает *args и **kwargs, а затем ничего не делает с ними? Передайте их в dict.__new__ следующим образом: dict.__new__(cls, *args, **kwargs). – GingerPlusPlus 31 December 2014 в 14:29
class Foo(object):
     pass

some_global_variable = Foo()

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

60
ответ дан Cat Plus Plus 16 August 2018 в 11:34
поделиться
  • 1
    почему вы сказали «Не использовать синглтоны»? Любая причина? – Alcott 20 September 2011 в 02:30
  • 2
    Это не будет работать, если синглтон должен быть маринован. Используя пример, который вы дали: s = some_global_variable; str = pickle.dumps(s); s1 = pickle.loads(str); print s is s1; # False – dividebyzero 20 January 2012 в 13:47
  • 3
    @dividebyzero: оператор is проверяет равенство указателя. Я был бы весьма удивлен - до того, чтобы называть его ошибкой - если pickle.loads вернул ссылку на ранее существовавший объект, а не ссылку на вновь созданный. Таким образом, тестирование того, что s is s1 ничего не говорит о пригодности использования модулей в качестве однотонных. – Jonas Kölker 17 February 2014 в 12:52
  • 4
    @ JonasKölker pickle.loads() делает это уже, например. для экземпляров bool и NoneType. pickle.loads(pickle.dumps(False)) is False дает True – Dan Passaro 28 April 2014 в 18:16
  • 5
    @ leo-the-manic: справедливая точка; однако это лишь побочный эффект Python, который интернирует объекты True, False и None и не имеет никакого отношения к коду, стоящему за pickle.loads. Кроме того, это безопасно делать только для объектов только для чтения. Если pickle.loads должен был возвратить ссылку на уже существующий объект modifiable , такой как модуль, который был бы ошибкой. (И поэтому я уверен, что пример кода dividebyzero ничего не доказывает). – Jonas Kölker 3 May 2014 в 01:18

Я подброшу на ринг. Это простой декоратор.

from abc import ABC

def singleton(real_cls):

    class SingletonFactory(ABC):

        instance = None

        def __new__(cls, *args, **kwargs):
            if not cls.instance:
                cls.instance = real_cls(*args, **kwargs)
            return cls.instance

    SingletonFactory.register(real_cls)
    return SingletonFactory

# Usage
@singleton
class YourClass:
    ...  # Your normal implementation, no special requirements.

Преимущества Я думаю, что он имеет некоторые из других решений:

  • Это понятно и кратким (на мой взгляд, D).
  • Его действие полностью инкапсулировано. Вам не нужно ничего менять в реализации YourClass. Это означает, что вам не нужно использовать метакласс для вашего класса (обратите внимание, что метаклас выше находится на фабрике, а не «реальный» класс).
  • Он не полагается на что-либо. g3]
  • Он прозрачен для вызывающих: звонящие по-прежнему просто импортируют YourClass, он выглядит как класс (потому что это так), и они обычно используют его. Нет необходимости адаптировать вызывающих абонентов к заводской функции. То, что YourClass() создает экземпляр, по-прежнему является истинным экземпляром YourClass, который вы внедрили, а не прокси-сервером любого типа, поэтому никаких шансов на побочные эффекты в результате этого. isinstance(instance, YourClass) и подобные операции все еще работают как ожидалось (хотя этот бит требует abc, поэтому исключает Python & lt; 2.6).

Для меня имеет место один недостаток: classmethods и staticmethods реального класса не могут быть прозрачно вызваны с помощью класса фабрики, скрывающего его. Я использовал это достаточно редко, что мне никогда не приходилось сталкиваться с этой необходимостью, но его можно было бы легко исправить, используя специальный метакласс на заводе, который реализует __getattr__(), чтобы делегировать доступ к атрибуту all-ish для реального класса.

Связанный шаблон, который я действительно нашел более полезным (не то, что я говорю, что такие вещи требуются очень часто вообще) является «уникальным» шаблоном, где экземпляр класса с помощью те же аргументы приводят к возврату одного и того же экземпляра. То есть «одиночный аргумент». Вышеприведенное адаптируется к этой скважине и становится еще более кратким:

def unique(real_cls):

    class UniqueFactory(ABC):

        @functools.lru_cache(None)  # Handy for 3.2+, but use any memoization decorator you like
        def __new__(cls, *args, **kwargs):
            return real_cls(*args, **kwargs)

    UniqueFactory.register(real_cls)
    return UniqueFactory

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

0
ответ дан CryingCyclops 16 August 2018 в 11:34
поделиться

Это мой предпочтительный способ реализации синглетонов:

class Test(object):
    obj = None

    def __init__(self):
        if Test.obj is not None:
            raise Exception('A Test Singleton instance already exists')
        # Initialization code here

    @classmethod
    def get_instance(cls):
        if cls.obj is None:
            cls.obj = Test()
        return cls.obj

    @classmethod
    def custom_method(cls):
        obj = cls.get_instance()
        # Custom Code here
-1
ответ дан fab 16 August 2018 в 11:34
поделиться
  • 1
    Это не строго синглтон, поскольку он допускает существование более одного экземпляра класса. Улучшение будет состоять в том, чтобы класс не мог быть инициализирован, и все методы класса действуют на атрибуты класса – theheadofabroom 30 October 2014 в 09:21
  • 2
    То есть статический класс – theheadofabroom 30 October 2014 в 09:23

Это решение вызывает некоторое загрязнение пространства имен на уровне модуля (три определения, а не только одно), но мне легко следовать.

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

# wouldn't it be nice if we could do this?
class Foo(object):
    instance = None

    def __new__(cls):
        if cls.instance is None:
            cls.instance = object()
            cls.instance.__class__ = Foo
        return cls.instance

Так как это невозможно, мы можем разбить инициализацию и статический экземпляр в

Ожидаемая инициализация:

import random


class FooMaker(object):
    def __init__(self, *args):
        self._count = random.random()
        self._args = args


class Foo(object):
    def __new__(self):
        return foo_instance


foo_instance = FooMaker()
foo_instance.__class__ = Foo

Ленивая инициализация:

Ижевая инициализация:

import random


class FooMaker(object):
    def __init__(self, *args):
        self._count = random.random()
        self._args = args


class Foo(object):
    def __new__(self):
        global foo_instance
        if foo_instance is None:
            foo_instance = FooMaker()
        return foo_instance


foo_instance = None
-1
ответ дан Gregory Nisbet 16 August 2018 в 11:34
поделиться

Ну, не соглашаясь с общим предложением Питонов о глобальном уровне модуля, как насчет этого:

def singleton(class_):
    class class_w(class_):
        _instance = None
        def __new__(class2, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w, class2).__new__(class2, *args, **kwargs)
                class_w._instance._sealed = False
            return class_w._instance
        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True
    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(object):
    def __init__(self, text):
        print text
    @classmethod
    def name(class_):
        print class_.__name__

x = MyClass(111)
x.name()
y = MyClass(222)
print id(x) == id(y)

Выход:

111     # the __init__ is called only on the 1st time
MyClass # the __name__ is preserved
True    # this is actually the same instance
2
ответ дан Guard 16 August 2018 в 11:34
поделиться
  • 1
    Какова точка атрибута _sealed? Насколько я вижу, это ничего не делает? Что-то меня обманывает, что говорит, что он не должен хорошо работать ... Я проведу несколько сравнительных тестов на этой неделе. – theheadofabroom 25 July 2011 в 11:32
  • 2
    _sealed гарантирует, что ваш init запускается только один раз; Я не вижу смысла, почему он должен работать хуже, чем обычный функциональный декоратор - функция выполняется только один раз для каждого класса и возвращает новый унаследованный класс – Guard 25 July 2011 в 20:29
  • 3
    BTW, ваше редактирование содержит вкладки, которые нарушают отступы. Вы также говорите: «Мы создаем 2 класса» - вы имеете в виду, что мы создаем «1 дополнительный класс»? – Guard 25 July 2011 в 20:31
  • 4
    Да, один дополнительный класс - это то, что я имел в виду. Я намерен включать материал в __init__ для вызова каждый раз, когда он инициализируется. Простое «Бытие инициализировано в классе.method». как для отступов - вы использовали вкладки и пробелы - я исправил большую часть из них, но, похоже, пропустил один, если вы хотите его получить (просто проверьте журнал изменений) – theheadofabroom 26 July 2011 в 07:33
  • 5
    re init : конечно, это зависит от вас, я просто попытался воспроизвести одноэлементное поведение на других языках, где код конструктора (который не совсем init , но очень близок в его смысл) вызывается только один раз, если вы хотите каждый раз вызывать init , просто убить все ссылки на _laled re spaces / tabs - ну, тогда мне emacs нужно исправление. в любом случае, выше - исправленная версия – Guard 26 July 2011 в 07:52

Вот вам один лайнер:

singleton = lambda c: c()

Вот как вы его используете:

@singleton
class wat(object):
    def __init__(self): self.x = 1
    def get_x(self): return self.x

assert wat.get_x() == 1

Ваш объект получает экземпляр с нетерпением. Это может быть или не быть тем, что вы хотите.

10
ответ дан Jonas Kölker 16 August 2018 в 11:34
поделиться
  • 1
    -1. Это очень плохо и глупо. Вы не определяете класс для использования в качестве объекта. Вы больше не можете обращаться к классу, не будучи очень уродливым, как type(wat) или wat.__class__. Если вы действительно хотите достичь этого, лучше определите класс и сразу создайте его, не нужно испортить декоратор. – 0xc0de 16 October 2014 в 08:56
  • 2
    Зачем вам нужно знать класс одного синглета? Просто используйте объект singleton. – Tolli 18 October 2014 в 00:41
  • 3
    Это не singleton pattern , поэтому IMO функцию следует называть по-разному. – GingerPlusPlus 30 December 2014 в 22:53
  • 4
    Википедия: «шаблон singleton - это шаблон проектирования, который ограничивает создание экземпляра одного объекта». Я бы сказал, что мое решение делает именно это. Хорошо, я думаю, что можно было бы сделать wat2 = type(wat)(), но это питон, мы все соглашаемся с взрослыми и все такое. Вы не можете гарантировать , что будет только один экземпляр, но вы можете гарантировать, что если люди сделают второй, он будет выглядеть уродливым и - если они приличные, стоящие люди - как предупреждение знак им. Что мне не хватает? – Jonas Kölker 2 January 2015 в 20:35

Это немного похоже на ответ fab, но не совсем то же самое.

Контракт singleton не требует, чтобы мы могли вызвать конструктор несколько раз. Поскольку одноэлемент должен создаваться один раз и один раз, разве это не должно быть создано только один раз? «Spoofing» конструктор, возможно, ухудшает удобочитаемость.

Итак, мое предложение таково:

class Elvis():
    def __init__(self):
        if hasattr(self.__class__, 'instance'):
            raise Exception()
        self.__class__.instance = self
        # initialisation code...

    @staticmethod
    def the():
        if hasattr(Elvis, 'instance'):
            return Elvis.instance
        return Elvis()

Это не исключает использования конструктора или поля instance код пользователя:

if Elvis() is King.instance:

... если вы точно знаете, что Elvis еще не создано и что King имеет.

Но он рекомендует пользователям использовать универсальный метод the:

Elvis.the().leave(Building.the())

Чтобы сделать это, вы также можете переопределить __delattr__(), чтобы поднять исключение, если попытка удалить instance , и переопределить __del__(), чтобы он вызывал исключение (если мы не знаем, что программа заканчивается ...)

Дальнейшие улучшения


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

try:
    # This is jython-specific
    from synchronize import make_synchronized
except ImportError:
    # This should work across different python implementations
    def make_synchronized(func):
        import threading
        func.__lock__ = threading.Lock()

        def synced_func(*args, **kws):
            with func.__lock__:
                return func(*args, **kws)

        return synced_func

class Elvis(object): # NB must be subclass of object to use __new__
    instance = None

    @classmethod
    @make_synchronized
    def __new__(cls, *args, **kwargs):
        if cls.instance is not None:
            raise Exception()
        cls.instance = object.__new__(cls, *args, **kwargs)
        return cls.instance

    def __init__(self):
        pass
        # initialisation code...

    @classmethod
    @make_synchronized
    def the(cls):
        if cls.instance is not None:
            return cls.instance
        return cls()

Оповещения:

  1. Если вы не подклассы объекта python2.x вы получите класс старого стиля, который не использует __new__
  2. . При декорировании __new__ вы должны украсить с помощью @classmethod, или __new__ будет методом несвязанного экземпляра
  3. Возможно, это возможно улучшить с помощью метакласса, поскольку это позволит вам сделать свойство the класса, возможно, переименовать его в instance
0
ответ дан mike rodent 16 August 2018 в 11:34
поделиться
  • 1
    Хотя это немного другая интерпретация одноэлементного шаблона, я уверен, что он по-прежнему действителен, хотя я могу искусить использование __new __, а не __init__, поскольку он чисто действует на атрибуты класса, и это мешает вкратце являясь вторым экземпляром. Разница между этим и методом 2 заключается в том, пытается ли попытка инициализации более одного раза возвращать один экземпляр или вызывает исключение. Я думаю, что я счастлив, что либо удовлетворяю одноэлементному шаблону, но и проще в использовании, тогда как другой более явный, что он является одноэлементным. – theheadofabroom 21 February 2016 в 10:40
  • 2
    Очевидно, использование имени класса в __init__ предотвращает подкласс, но в то время как это упрощает задачу, это не требуется – theheadofabroom 21 February 2016 в 10:43
  • 3
    Спасибо ... ах да, мгновенный второй экземпляр до того, как Exception будет выброшено. Я изменил __init__ так, что, надеюсь, это должно быть подклассы ... – mike rodent 21 February 2016 в 10:51
  • 4
    Классный, the, вероятно, может быть полезен для класса класса по аналогичным причинам – theheadofabroom 21 February 2016 в 11:32
  • 5
    Да, ты прав. Затем вы можете использовать подклассы SuperElvis singleton и (например) подклассы ImaginaryElvis singleton ... и они могут сосуществовать. Смотрите дополнительные мысли. Не стесняйтесь улучшать свой код. – mike rodent 21 February 2016 в 12:35

Вот моя собственная реализация синглетонов. Все, что вам нужно сделать, это украсить класс; для получения синглтона вы должны использовать метод Instance. Вот пример:

   @Singleton
   class Foo:
       def __init__(self):
           print 'Foo created'

   f = Foo() # Error, this isn't how you get the instance of a singleton

   f = Foo.Instance() # Good. Being explicit is in line with the Python Zen
   g = Foo.Instance() # Returns already created instance

   print f is g # True

И вот код:

class Singleton:
    """
    A non-thread-safe helper class to ease implementing singletons.
    This should be used as a decorator -- not a metaclass -- to the
    class that should be a singleton.

    The decorated class can define one `__init__` function that
    takes only the `self` argument. Other than that, there are
    no restrictions that apply to the decorated class.

    To get the singleton instance, use the `Instance` method. Trying
    to use `__call__` will result in a `TypeError` being raised.

    Limitations: The decorated class cannot be inherited from.

    """

    def __init__(self, decorated):
        self._decorated = decorated

    def Instance(self):
        """
        Returns the singleton instance. Upon its first call, it creates a
        new instance of the decorated class and calls its `__init__` method.
        On all subsequent calls, the already created instance is returned.

        """
        try:
            return self._instance
        except AttributeError:
            self._instance = self._decorated()
            return self._instance

    def __call__(self):
        raise TypeError('Singletons must be accessed through `Instance()`.')

    def __instancecheck__(self, inst):
        return isinstance(inst, self._decorated)
3
ответ дан Paul Manta 16 August 2018 в 11:34
поделиться
  • 1
    Это не правда, синглтон. SingletonList = Singleton(list).Instance(); print(SingletonList is type(SingletonList)()) должен печатать True в истинном одиночном режиме; с вашими отпечатками кода False – GingerPlusPlus 30 December 2014 в 23:07
  • 2
    @GingerPlusPlus Я знал несколько ограничений, но не тот, который вы указали. Спасибо, что упомянул об этом. К сожалению, у меня нет времени на то, чтобы окунуться в какое-то решение. – Paul Manta 30 December 2014 в 23:19
12
ответ дан Peter Mortensen 16 August 2018 в 11:34
поделиться
  • 1
    конечно, это не метакласс - в python3 для использования метакласса для построения MyClass вы сделали бы class MyClass(metaclass=Singleton) – theheadofabroom 30 July 2013 в 15:32
  • 2
    Ссылка mikewatkins.ca (эффективно) нарушена. – Peter Mortensen 14 March 2016 в 22:54
  • 3
    В основном это правда, но иногда этого недостаточно. Например. У меня есть проект с необходимостью регистрировать экземпляры многих классов на уровне DEBUG. Мне нужно, чтобы параметры командной строки обрабатывались при запуске, чтобы установить указанный пользователем уровень ведения журнала до , эти экземпляры создаются. Импотенты на уровне модуля делают это проблематичным. Возможно, я мог бы тщательно структурировать приложение, чтобы все эти классы не импортировались до тех пор, пока обработка CLI не будет выполнена, но естественная структура моего приложения важнее, чем догматическое присоединение к «синглонам плохо», поскольку они могут делайте это довольно чисто. – CryingCyclops 27 August 2016 в 21:29
  • 4
    если бы вы тестировали свой код во время исправления my_singleton, это было бы возможно? поскольку этот my_singleton может быть создан в другом модуле. – Naveen 24 April 2018 в 03:04
  • 5
    @Naveen - my_singleton - это единственный объект. Если вы "патч" это изменение повлияет на все будущие ссылки, даже в других модулях. – Alan Dyke 24 April 2018 в 19:30

Один вкладыш (я не горжусь, но он выполняет эту работу):

class Myclass:
  def __init__(self):
      # do your stuff
      globals()[type(self).__name__] = lambda: self # singletonify
1
ответ дан polvoazul 16 August 2018 в 11:34
поделиться

Этот ответ скорее всего не то, что вы ищете. Мне нужен синглтон в том смысле, что только этот объект имел свою идентичность для сравнения. В моем случае это использовалось как Sentinel Value . Для чего ответ очень прост, сделайте любой объект mything = object() и природой питона, только эта вещь будет иметь свою идентичность.

#!python
MyNone = object()  # The singleton

for item in my_list:
    if item is MyNone:  # An Example identity comparison
        raise StopIteration
-1
ответ дан ThorSummoner 16 August 2018 в 11:34
поделиться
  • 1
    Я узнал, что модули могут быть импортированы несколько раз, в этом случае это только локальный синглтон, который на самом деле не является синглом в любой емкости. – ThorSummoner 23 March 2018 в 21:00

Как насчет этого:

def singleton(cls):
    instance=cls()
    cls.__new__ = cls.__call__= lambda cls: instance
    cls.__init__ = lambda self: None
    return instance

Используйте его как декоратор в классе, который должен быть одноэлементным. Например:

@singleton
class MySingleton:
    #....

Это похоже на декоратор singleton = lambda c: c() в другом ответе. Как и в другом решении, единственный экземпляр имеет имя класса (MySingleton). Однако с помощью этого решения вы все равно можете «создать» экземпляры (фактически получить единственный экземпляр) из класса, выполнив MySingleton(). Это также мешает вам создавать дополнительные экземпляры, выполняя type(MySingleton)() (который также возвращает тот же экземпляр).

1
ответ дан Tolli 16 August 2018 в 11:34
поделиться
  • 1
    Вы не определяете класс, чтобы использовать его в качестве объекта. – 0xc0de 16 October 2014 в 09:00
  • 2
    Каждый раз, когда вы вызываете type(MySingleton)(), вызывается MySingleton.__init__(), и объект получает инициализацию несколько раз; вы можете исправить это, записав cls.__init__ = lambda self: pass в свой singleton. Кроме того, переопределение cls.__call__ кажется бессмысленным и даже вредным - __call__, определенным в этом контексте, используется, когда вы вызываете MySingleton(any, list, of, arguments), а не когда вы вызываете type(MySingleton)(any, list, of, arguments). – GingerPlusPlus 31 December 2014 в 14:23
  • 3
    @GingerPlusPlus, спасибо за указание, что __init__() снова вызывается при выполнении type(MySingleton)(). Предлагаемое вами решение (добавление cls.__init__ = lambda self: pass) дает синтаксическую ошибку, потому что последняя часть выражения лямбда должна быть выражением, а не выражением. Однако добавление cls.__init__ = lambda self: None работает, поэтому я добавил это к моему ответу. – Tolli 2 January 2015 в 06:42
  • 4
    @GingerPlusPlus, Что касается использования __call__. мое намерение состояло в том, чтобы вернуть оба экземпляра type(MySingleton)() и MySingleton(). Так он делает то, что я хотел. Вы можете думать о том, что MySingleton является либо типом синглтона, либо экземпляром синглтона (или обоих). – Tolli 2 January 2015 в 06:43

Используйте модуль. Он импортируется только один раз. Определите в нем глобальные переменные - они будут атрибутами singleton. Добавьте некоторые функции - методы «singleton».

49
ответ дан warvariuc 16 August 2018 в 11:34
поделиться
  • 1
    Так что вы в конечном итоге ... Это не класс. Вы не можете использовать его как класс, вы не можете основывать на нем другие классы, вы используете синтаксис импорта, и вдруг вы теряете все преимущества ООП ... – theheadofabroom 25 July 2011 в 14:04
  • 2
    если вы можете основывать на нем другие классы, то это может быть не одиночный. вы можете создать один из производного класса, но также и один из базового класса, но производный класс также является членом базы, и у вас есть две базы, какую из них вы должны использовать? – SingleNegationElimination 25 July 2011 в 20:32
  • 3
    Это не работает через модули. В моей "основной" модуль i задает значение. Затем я ссылаюсь на него в другом модуле и его нулевом значении. Вздох. – Paul Kenjora 30 March 2017 в 14:20
  • 4
    @PaulKenjora У вас должна быть ошибка в вашем коде. Если вы определяете глобальную переменную в модуле, когда вы обращаетесь к ней с другого модуля, она должна иметь значение. – warvariuc 30 March 2017 в 19:40
  • 5
    Он имеет значение, но когда я его изменяю, он не сохраняется. Я закончил использование класса со свойствами в модуле, который работает. Простые типы, поскольку глобальные переменные не работали для меня (они потеряли значения, как только сфера изменилась). – Paul Kenjora 13 April 2017 в 18:32
13
ответ дан Peter Mortensen 6 September 2018 в 05:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: