Найти - Пользователи
Полная версия: Питон и синглтон
Начало » Python для новичков » Питон и синглтон
1
sanovskiy
Есть замечательный паттерн программирования синглтон. Он гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.

Задался вот целью реализовать в питоне этот паттерн.
Получилось вот что:

Файл concon.py
import time, sys

class ConsoleController( object ):
_iInstance = None

class __Singleton:
_selfUsed = 0
_startTime = 0
_endTime = 0
_echoLevel=0
_indentStr = '\t'

def __init__(self):
self._startTime = self.getTime()

def __del__(self):
self._endTime = self.getTime()
timeElapsed = self._endTime - self._startTime
self \
.dropText('Script finished.') \
.dropText('Elapsed time: '+str(timeElapsed) + ' sec')

def getTime(self):
return time.time()

def cEcho(self,str):
sys.stdout.write(str)
return self

def dropLF(self):
self.cEcho('\n')
return self

def dropText(self,str,colorize=None):
self \
.dropIndent() \
.cEcho(str) \
.dropLF()
return self

def dropIndent(self):
self.cEcho(self._indentStr*self._echoLevel)
return self

def indentIncrease(self):
self._echoLevel += 1
return self

def indentDecrease(self):
self._echoLevel -= 1
if self._echoLevel < 0:
self._echoLevel = 0
return self

def __init__( self ):
if ConsoleController._iInstance is None:
ConsoleController._iInstance = ConsoleController.__Singleton()
self.__dict__['_EventHandler_instance'] = ConsoleController._iInstance
ConsoleController._iInstance._selfUsed += 1;

def __getattr__(self, aAttr):
return getattr(self._iInstance, aAttr)

def __setattr__(self, aAttr, aValue):
return setattr(self._iInstance, aAttr, aValue)

def __del__(self):
ConsoleController._iInstance._selfUsed -= 1
# print 'Links: ' + str(ConsoleController._iInstance._selfUsed)
if ConsoleController._iInstance._selfUsed == 0:
self._iInstance.__del__()
Собственно вопрос:
Есть ли способ сделать код изящнее? Очень напрягает оперирование свойством _selfUsed
Плюс вследствие этого в начале скрипта просто необходимо обязательно создать инстанс ConsoleController иначе деструктор вложенного класса Singleton будет вызываться чаще одного раза.

Вот например в этом случае:
import concon

def diveIn(maxDeep=1,curDeep=0):
CC = ConsoleController()
CC.indentIncrease()
CC.dropText('In!')
if maxDeep>curDeep:
nextDeep = curDeep+1
diveIn(maxDeep,nextDeep)
CC.dropText('Out!')
CC.indentDecrease()

diveIn(4)

CC = ConsoleController()
CC.dropText('Destruct message will be shown after this line!')
sanovskiy
PooH
http://python.su/forum/viewtopic.php?id=1786
http://www.iso.ru/journal/articles/143.html
спасибо за ссылки, но проблему с
Sanovskiy
в начале скрипта просто необходимо обязательно создать инстанс ConsoleController иначе деструктор вложенного класса Singleton будет вызываться чаще одного раза.
это не решило.

Проблема в том, что __del__ теперь вообще не вызывается.
Александр Кошелев
sanovskiy
Есть ли способ сделать код изящнее?
Лучший синглтон в питоне это модуль.
Viper
В качестве замены синглтону в питоне мне нравится метод Борга.
bw
Я бы сделал так:

class Singleton(object):
instance_ref = None

def __new__(cls, *args, **kwargs):
if cls.instance_ref is None or cls.instance_ref() is None:
import weakref
instance = object.__new__(cls, *args, **kwargs)
cls.instance_ref = weakref.ref(instance)
if hasattr(cls, '__hidden_init__'):
cls.__init__ = cls.__hidden_init__
del cls.__hidden_init__
elif hasattr(cls, '__init__') and not hasattr(cls, '__hidden_init__'):
cls.__hidden_init__ = cls.__init__
cls.__init__ = lambda *args, **kwargs: None
return cls.instance_ref()
>>> a = Singleton()
>>> b = Singleton()
>>> a is b
True
..bw
Lexander
Метод Борга очень изящный.
sanovskiy
Спасибо за ответы.
Метод Борга действетельно изящен.
По сути, кого волнует id? :))
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB