Объясните класс Python Singleton - PullRequest
0 голосов
/ 11 июня 2018
class Singleton:

    instance = None

    def __new__(cls):
        if cls.instance is None:
            cls.instance = super().__new__(cls)
        return cls.instance

singleton_obj1 = Singleton()
singleton_obj2 = Singleton()

print(singleton_obj1)
print(singleton_obj2)

вывод

<__main__.Singleton object at 0x10dbc0f60>
<__main__.Singleton object at 0x10dbc0f60>

Может кто-нибудь объяснить, что именно происходит в этой строке cls.instance = super().__new__(cls).Какие строки кода помогли сделать этот класс Singleton?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Хорошо, чтобы перейти к этому болезненно подробно:

class Singleton: неявно наследуется от Object, потому что в python все является объектом.

instance = None читается только во время загрузки модуля и устанавливает переменную уровня класса instance равной None один раз , но может быть перезаписана отдельными экземплярами класса Singleton.

def __new__(cls):
    if cls.instance is None:
        cls.instance = super().__new__(cls)
    return cls.instance

(Во-первых, я думаю, что это странно, что они помещают туда "cls", я знаю, почему они это сделали, потому что это относится к классу в целом , а не к конкретному экземпляруэтот класс. Но, это может сбивать с толку, поэтому кто-то, кто не знает, на что они смотрят. В любом случае ...)

__new__ - это магическая функция, которая вызывается до __init__, чтопримерно аналогично выделению места для нового экземпляра класса.Здесь cls.instance был установлен на None при загрузке модуля, и поэтому каждый раз, когда создается новый Singleton, этот тест проводится.Поскольку cls.instance устанавливается при первом создании Singleton, super().__new__(cls) также вызывается только один раз .Суперкласс Singleton - это Object.Таким образом, поведение super().__new__(cls) в точности соответствует ожидаемому для любого другого создаваемого вами класса.
Если вы создаете второй (или третий / четвертый / пятый ...) экземпляр Singleton тогда этот super().__new__(cls) не будет вызван.Вместо этого возвращается переменная уровня класса instance, означающая, что новые экземпляры Singleton не могут быть созданы .

Когда вы печатаете экземпляры Singleton, вы можете увидетьадрес памяти 0x10dbc0f60 одинаков для обоих «экземпляров», потому что cls.instance возвращается во время __new__, которое можно рассматривать как время выделения памяти до вызова __init__.

Этоэто хороший способ сделать шаблон Singleton, потому что теперь для создания одноэлементного класса все, что вам нужно сделать, это наследовать от Singleton, и тяжелая работа уже сделана.Вы продолжаете и используете __init__, как обычно, и не беспокоитесь об этом.Каждый раз, когда вы создаете «новый» экземпляр этого класса, вы получаете тот же экземпляр обратно.Полностью за кадром.

Это довольно продвинутые вещи, но посмотрите, как это просто.Питон самый лучший!

0 голосов
/ 11 июня 2018

Конструктор говорит:

If there is no instance recorded, 
   create an instance and record it
return the recorded instance

Это стандартный шаблон проектирования Singleton, для большинства языков, чтобы обеспечить создание только одного экземпляра класса.

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