Singleton
A weblaboron olvastam ma egy cikket inf3rno tollából, amely az ősosztályként megvalósított singleton problémáját járja körül PHP-ban. (Egyke tervezési minta, de én nem szeretem az ilyeneket lefordítani, mert nagyon suta tud lenni, szerintem.) Pythonban sem egyértelmű a dolog, a klasszikus "legyen privát a konstruktor, és egy metódus adja vissza a példányt" megoldás nem működik, mert pythonban a konstruktor mindig publikus. Ennek ellenére nem az okoz nehézséget, hogy hogyan valósítsuk meg a singletont, hanem hogy a lehetőségek közül melyiket válasszuk :)
Nézzünk néhány példát, a teljesség igénye nélkül! Nem kell megijedni, ha kezdőbb olvasók nem teljesen értik a példákat, megértésükhöz szükséges a python nyelv bizonyos szintű ismerete.
1. Singleton ősosztály
A legelső megvalósítás, ami leginkább hasonlít a klasszikusra, illetve a fenti cikkben megvalósítottra, az egy ősosztály, amelyből leszármaztatott osztályaink is singletonok lesznek.
class Singleton(object): __instance = None def __new__(klass): if type(klass.__instance) != klass: klass.__instance = object.__new__(klass) return klass.__instance @classmethod def getInstance(klass): return klass()
A getInstance metódust csak a rend kedvéért csináltam, maga a "konstruktor" adja vissza az egyetlen létező példányt, a getInstance csak őt hívja.
>>> class MySingleton(Singleton): ... def setA(self, a): ... self.a = a ... >>> ms1 = MySingleton() >>> ms2 = MySingleton() >>> ms3 = MySingleton.getInstance() >>> ms1 is ms2 is ms3 True >>> ms1.setA(5) >>> ms2.a += 10 >>> ms3.a 15
Működni látszik :)
2. Singleton Metaclass
A python a metaprogramozás kedvelőinek is nyújt csemegéket, ilyenek például a metaclassok, azaz az "osztály generátor osztályok". Ezekről majd kicsit később talán bővebben is lesz szó, de most lássunk egy metaclass alapú singleton megvalósítást:
class SingletonMeta(type): def __init__(klass, name, bases, dict): super(SingletonMeta, klass).__init__(name, bases, dict) klass.__instance = None def __call__(klass, *args, **kwargs): if klass.__instance is None: klass.__instance = super(SingletonMeta, klass).__call__(*args, **kwargs) return klass.__instance def getInstance(klass): return klass()
Lássunk példát a használatára:
>>> class MySingleton2(object): ... __metaclass__ = SingletonMeta ... def setA(self, a): ... self.a = a ... >>> ms1 = MySingleton2() >>> ms2 = MySingleton2() >>> ms1 is ms2 True
A singleton tulajdonság továbböröklődik a gyermekosztály felé is:
>>> class A(MySingleton2): ... def getA(self): ... return self.a ... >>> a1 = A.getInstance() >>> a2 = A() >>> a1 is a2 True >>> a1.setA(42) >>> a2.getA() 42
3. Assimilate! - A Borg
Vannak fejlesztők, akik nem szeretik a singleton mintát bizonyos célokra, és szeretnek különálló - de azonos tudattal rendelkező - objektumokat használni. A python számukra is nyújt megoldást, ez pedig a Borg minta.
class Borg(object): __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state
Szintén leszármazhatunk belőle - bár ezt a két extra sort akár be is írhatjuk a saját Borg-ősnek szánt osztályunkba. A Borg objektumok különálló objektumok lesznek, csak a "tudatuk", azaz a belső állapotuk lesz közös. (Hirtelen nem jut eszembe olyan eset, ahol ez jobb, mint a hagyományos singleton minta, de már láttam rá példát.)
>>> class B(Borg): ... def setB(self, b): ... self.b = b ... >>> b1 = B() >>> b2 = B() >>> b1 is b2 False >>> b1.setB(42) >>> b1.b 42 >>> b1.b is b2.b True
4. Singleton dekorátor
Hagyományos osztályainkat is felruházhatjuk (kvázi utólag) singleton tulajdonsággal. Van hogy az osztályt mások készítették, mi csak felhasználnánk, esetleg OOP nézeteinkbe nem illeszkedik, hogy a Fold az egy Singleton és nem pedig csak egy Bolygo (persze pythonban mindkettő lehet egyszerre, mert van többszörös öröklődés). Vagy csak mért így egyszerűbb.
def singleton(klass): instances = {} def getInstance(): if klass not in instances: instances[klass] = klass() return instances[klass] return getInstance
A dekorátor kódja a legegyszerűbb talán az eddigiek közül, ehhez elég "csak" azt tudni, hogy mi az a dekorátor :)
Példa a felhasználásra:
>>> @singleton ... class C(object): ... def setC(self, c): ... self.c = c ... >>> c1 = C() >>> c2 = C() >>> c1 is c2 True >>> ImpSingleton = singleton(ImportaltOsztaly) >>> i1 = ImpSingleton() >>> i2 = ImpSingleton() >>> i1 is i2 True
Egyelőre ennyi, hazaértemkor gondoltam hipp-hopp összeírom a gondolataimat a témával kapcsolatban, és az előbb szóltak - jogosan -, hogy kb. 2 órája ezt a postot írom. Mégegyszer hangsúlyozom, nem kell megijedni, ha nem érthető minden elsőre, másodikra se biztos, hogy az lesz, de ha a tervek szerint írogatok ide, akkor pár hónap múlva visszalapozva mindennek egyértelműnek kell majd lennie - majd igyekszem :)
A fent megvalósított osztályok letölthetőek innen: singleton.py
Posted
by
Szia, én is olvastam a weblaboron. És egy szót sem értettem. Ez azért van mert nem értek az oophez. Tudnál valami magyar könyvet ajánlani amit ha elolvasnék, már érteném mikről van itt szó? Köszi.
En szakmai nyomtatott konyveket nemnagyon szoktam olvasni, OOP-t az egyetemen tanultunk, de igazan hasznalat - mondjuk munka - kozben erti meg a dolgokat, hogy mit hogyan, es miert erdemes csinalni. Az OOP alapok utan pedig erdemes megnezegetni a tervezesi mintakat (design patterns), amikhez szerintem nem kell szo szerint ragaszkodni - mintak, es nem szabvanyok vagy szabalyok - de otletet meriteni beloluk mindenkepp erdemes. Azt pedig, hogy objektum orientalt python programozast milyen konyvbol tudnal tanulni, arrol vegkepp fogalmam nincs, de nagyon sok nyilt forrasu python project van, aminek a kodjabol nagyon sokat lehet tanulni, illetve majd igyekszem kezdobb cikkeket is irni.
Remeljuk olyasvalaki is olvassa majd ezt, aki tud konyvet ajanlani :)
Most éppen az alábbiakat olvasom és használhatónak tűnnek:
Gérard Swinnen: Tanuljunk meg programozni Python nyelven. bz2-be tömöritve elérhető itt: http://python.free-h.net/spip.php?article4
A http://pythonlib.pergamen.hu/ lapon és a http://python.free-h.net lapon sok egyéb mellet:
Bevezetés a Pythonba példákkal elérhető itt: http://python.free-h.net/spip.php?article3
Illetve ezt is érdemes olvasgatni: http://pythonlib.pergamen.hu/download/tut.pdf
Köszi és oop ügyileg tudnál ajánlani valamit ami ehhez az egészhez szükséges?
Sajnos en nem vagyok valami nagy konyvolvaso, az egytemen tanultakon kivul leginkabb blogpostokbol, illetve opensource projectek nezegetesevel tanultam meg, amit tudok.
Remelem vannak masok, akik tudnak jo szakirodalmat ajanlani (slink?), illetve ha mar az OOP alapjaival tisztaban vagy, akkor erdemes atfutni a tervezesi mintakat (design patterns), amikrol szinten bizonyara van sok jo konyv, de attekinteshez jo a wikipedia cikk is.