Уведомления

Группа в Telegram: @pythonsu

#1 Июль 6, 2009 12:53:46

sanovskiy
От:
Зарегистрирован: 2009-07-06
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Питон и синглтон

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

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

Файл 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!')



Офлайн

#2 Июль 6, 2009 13:14:18

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Питон и синглтон

http://python.su/forum/viewtopic.php?id=1786
http://www.iso.ru/journal/articles/143.html



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#3 Июль 6, 2009 13:37:16

sanovskiy
От:
Зарегистрирован: 2009-07-06
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Питон и синглтон

PooH
http://python.su/forum/viewtopic.php?id=1786
http://www.iso.ru/journal/articles/143.html
спасибо за ссылки, но проблему с
Sanovskiy
в начале скрипта просто необходимо обязательно создать инстанс ConsoleController иначе деструктор вложенного класса Singleton будет вызываться чаще одного раза.
это не решило.

Проблема в том, что __del__ теперь вообще не вызывается.



Отредактировано (Июль 6, 2009 13:51:53)

Офлайн

#4 Июль 6, 2009 14:35:35

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Питон и синглтон

sanovskiy
Есть ли способ сделать код изящнее?
Лучший синглтон в питоне это модуль.



Офлайн

#5 Июль 6, 2009 16:39:33

Viper
От:
Зарегистрирован: 2006-11-08
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

Питон и синглтон

В качестве замены синглтону в питоне мне нравится метод Борга.



Офлайн

#6 Июль 6, 2009 17:34:44

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

Питон и синглтон

Я бы сделал так:

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



Отредактировано (Июль 6, 2009 17:50:15)

Офлайн

#7 Июль 6, 2009 18:30:06

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Питон и синглтон

Метод Борга очень изящный.



Офлайн

#8 Июль 7, 2009 09:43:06

sanovskiy
От:
Зарегистрирован: 2009-07-06
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

Питон и синглтон

Спасибо за ответы.
Метод Борга действетельно изящен.
По сути, кого волнует id? :))



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version