Tək nömrələri müəyyən etmək üçün sadə, zərif bir yol varmı?

Python'ta tekliğini müəyyən etmək üçün bir çox yol var. Yığın daşması barədə fikir birliyi varmı?

379
28 авг. 28 Avqust tarixində Jamie tərəfindən təyin olundu 2008-08-28 12:03 '08 at 12:03 2008-08-28 12:03
@ 22 cavab

Mən, həqiqətən, heç bir ehtiyac görmürəm, çünki bir funksiya (bir siniflə deyil) ilə bir modul təkli olaraq xidmət edəcəkdir. Onun bütün dəyişənləri hər halda yenidən yaradılan bir modulla əlaqələndiriləcək.

Bir sınıftan istifadə etmək istəyirsinizsə, Python'da xüsusi siniflər və ya xüsusi konstruktorlar yaratmaq üçün bir yol yoxdur, beləliklə API-lərdən istifadə edərək razılıq əldə etmədən bir çox hallara qarşı qala bilməzsiniz. Mən hələ modul daxil modul daxil və modul bir singleton baxmaq olardı.

313
28 авг. Cavab verilir, Staale 28 aug. 2008-08-28 12:10 '08 at 12:10 pm 2008-08-28 12:10

İşdə özümün tək həyata keçirilməsi. Bütün etmək lazımdır, sinfi bəzəyir; Singleton almaq üçün Instance metodunu istifadə Instance . Burada bir nümunə:

 @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 
border=0

Və burada kodu var:

 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. Also, the decorated class cannot be inherited from. 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. """ 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) 
270
08 сент. Cavab Paul Manta tərəfindən verilir 08 Sep. 2011-09-08 12:46 '11 'da 12:46' də 2011-09-08 12:46

__new__ üsulunu aşağıdakı kimi əvəz edə bilərsiniz:

 class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton, cls).__new__( cls, *args, **kwargs) return cls._instance if __name__ == '__main__': s1 = Singleton() s2 = Singleton() if (id(s1) == id(s2)): print "Same" else: print "Different" 
174
27 нояб. 27 noyabrda jojo tərəfindən verilmiş cavab 2009-11-27 22:37 '09 saat 22:37 'da 2009-11-27 22:37

Python'ta bir singleleton tətbiq etmək üçün bir az fərqli yanaşma, Alex Martelli'nin (bir Google işçisi və Python'un dahi) borg modelidir .

 class Borg: __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state 

Buna görə, bütün hallarda eyni identifikatora sahib olmaq yerinə, dövləti bölmək.

104
28 авг. Peter Hoffmann tərəfindən verilmiş cavab 28 avqust. 2008-08-28 17:53 '08 at 17:53 2008-08-28 17:53

Modul yanaşması yaxşı işləyir. Mən mütləq bir təkəlməyə ehtiyac duyarsam, Metaclass anlayışını üstün tuturam.

 class Singleton(type): def __init__(cls, name, bases, dict): super(Singleton, cls).__init__(name, bases, dict) cls.instance = None def __call__(cls,*args,**kw): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kw) return cls.instance class MyClass(object): __metaclass__ = Singleton 
75
28 авг. Cavab verilir 28 avqu. 2008-08-28 22:39 '08 at 10:39 pm 2008-08-28 22:39

PEP318- dən bu tətbiqə baxın, dekoratordan istifadə edərək tək nümunə modelini tətbiq edin:

 def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass: ... 
41
02 мая '10 в 5:47 2010-05-02 05:47 Cavab Wei tərəfindən mayın 02-də saat 5: 47-da verilir. 2010-05-02 05:47

Qəbul edilən cavabda qeyd olunduğu kimi, ən iddiasız üsul moduldan istifadə etməkdir .

Bunu nəzərə alaraq, burada konsepsiyanın sübutudur:

 def singleton(cls): obj = cls() # Always return the same object cls.__new__ = staticmethod(lambda cls: obj) # Disable __init__ try: del cls.__init__ except AttributeError: pass return cls 

__new__ haqqında daha ətraflı məlumat üçün Python məlumat modelinə baxın .

Məsələn:

 @singleton class Duck(object): pass if Duck() is Duck(): print "It works!" else: print "It doesn't work!" 

Qeydlər:

  • Bunun üçün, yeni stil siniflərindən istifadə etməlisiniz ( object əsaslanaraq).

  • Sintaksis müəyyənləşdirildikdən sonra ilk dəfə istifadə olunmur.

  • Bu oyuncaq nümunəsidir. Mən bunu istehsal kodunda heç vaxt istifadə etməmişəm və onu planlaşdırmıram.

26
12 окт. Cavab 12 oktyabrda Lambda Fairy tərəfindən verilir . 2012-10-12 03:13 '12 at 3:13 2012-10-12 03:13

Bir dəfə Pythonda single yazdım. Bütün üzv funksiyalarının bir sinif dekoratoru olduğu bir sinif istifadə etdim.

 class foo: x = 1 @classmethod def increment(cls, y = 1): cls.x += y 
14
29 авг. David Locke tərəfindən verilmiş cavab Aug 29 2008-08-29 22:15 '08 at 10:15 pm 2008-08-29 22:15

Python sənədləri bunları əhatə edir:

 class Singleton(object): def __new__(cls, *args, **kwds): it = cls.__dict__.get("__it__") if it is not None: return it cls.__it__ = it = object.__new__(cls) it.init(*args, **kwds) return it def init(self, *args, **kwds): pass 

Yəqin ki, bunu daha çox oxumaq üçün yenidən yaza bilərəm:

 class Singleton(object): """Use to create a singleton""" def __new__(cls, *args, **kwds): """ >>> s = Singleton() >>> p = Singleton() >>> id(s) == id(p) True """ self = "__self__" if not hasattr(cls, self): instance = object.__new__(cls) instance.init(*args, **kwds) setattr(cls, self, instance) return getattr(cls, self) def init(self, *args, **kwds): pass 

Bunu genişləndirmək üçün nisbətən təmiz olmalıdır:

 class Bus(Singleton): def init(self, label=None, *args, **kwds): self.label = label self.channels = [Channel("system"), Channel("app")] ... 
13
17 июля '12 в 9:38 2012-07-17 09:38 Cavab Brian Bruggeman tərəfindən 17 iyul 'da saat 9:38' da verilir. 2012-07-17 09:38

Mən bu mövzuda çox əmin deyiləm, amma DataController "şərtli tək" istifadə olunur (tək DataController , yəni DataController adlı bir sinif DataController , onu eyni modulda müəyyənləşdirirəm:

 _data_controller = None def GetDataController(): global _data_controller if _data_controller is None: _data_controller = DataController() return _data_controller 

Tam altı xətt olduğu üçün, bu zərif deyil. Amma bütün singletlerim bu şablondan istifadə edir və ən azı çox aydındır (pythondur).

12
22 авг. Cavab verilir u0b34a0f6ae 22 aug. 2009-08-22 03:44 '09 at 3:44 2009-08-22 03:44

Google Sınaq bloqunda bir təkliğin pis ola biləcəyi və anti-şablon olduğunun səbəblərini müzakirə edən maraqlı məqalələr var:

9
15 сент. Cavab FrankS 15 sentyabr tərəfindən verilir. 2008-09-15 10:47 '08 at 10:47 2008-09-15 10:47

Gələcəkdə dərsləri dekorativləşdirmək istəyirsinizsə, bir təkli dekoratorun yaradılması (aka annotasiya) zərif bir üsuldur. Sonra sınıftanızı təyin etməzdən əvvəl sadəcə @singleton qoyursunuz.

 def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass: ... 
9
23 февр. Cavab 23 fevralda Matt Alcock tərəfindən verilir. 2012-02-23 01:16 '12 saat 01:16 'da 2012-02-23 01:16

Burada Peter Norviq Python IAQ-a bir nümunədir Python-da təkli şablonu necə etmək olar? (Bu sorunu tapmaq üçün brauzerinizin axtarış funksiyasından istifadə etməlisiniz, heç bir əlaqə yoxdur, üzr)

Bruce Ekkel də Python'da Düşüncə kitabında başqa bir nümunə var (yenə kodun birbaşa bağlantısı yoxdur)

7
28 авг. cavab Serge 28 avqusta verilir . 2008-08-28 12:13 '08 at 12:13 2008-08-28 12:13

Hesab edirəm ki, tək bir sinif və ya bir nümunə zorla tələb olunur. Şəxsən normal bir sinif nümunəsini, yarı-xüsusi bir keçid və sadə bir fabrik funksiyasını təyin etmək istəyirəm.

 class NothingSpecial: pass _the_one_and_only = None def TheOneAndOnly(): global _the_one_and_only if not _the_one_and_only: _the_one_and_only = NothingSpecial() return _the_one_and_only 

Və ya ilk dəfə modul idxal edərkən bir nümunə yaratmaqla problem yoxdursa:

 class NothingSpecial: pass THE_ONE_AND_ONLY = NothingSpecial() 

Beləliklə, təzə nümunələrə yan təsirlərsiz testlər yaza bilərsiniz və modul qlobal operatorlarla serpilməyə ehtiyac yoxdur və zəruri hallarda gələcəkdə variantları əldə edə bilərsiniz.

5
27 июля '11 в 15:00 2011-07-27 15:00 Mark Evansın 27 İyul 2011-ci il saat 15.00-da cavab verdiyi 2011-07-27 15:00

Pythonun istifadə etdiyi Singleton şablonu ActiveState tərəfindən təmin edilir.

Göründüyü kimi, hiylə başqa bir sinifdə yalnız bir nümunəyə malik bir sinif qoymaqdır.

3
03 сент. Mark Biek tərəfindən verilmiş cavab 03 Sep. 2008-09-03 23:54 '08 at 23:54 2008-09-03 23:54

Bəli, təklin yaxşı və ya pis ola bilər, bilirəm. Bu mənim tətbiqimdir və yalnız klassik yanaşma daxilində önbelleği yerləşdirmək və başqa bir növün bir çox nümunəsini yaratmaq və ya, məsələn, eyni tipli bir çox nümunə yaratmaq amma müxtəlif arqumentlər ilə genişləndirirəm.

Mən bunu Singleton_group adlandırdım, çünki eyni qrupları birlikdə birləşdirir və həmin dəlilləri eyni sinif obyektinin yaradılmasını maneə törədir:

 # Peppelinux cached singleton class Singleton_group(object): __instances_args_dict = {} def __new__(cls, *args, **kwargs): if not cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))): cls.__instances_args_dict[(cls.__name__, args, str(kwargs))] = super(Singleton_group, cls).__new__(cls, *args, **kwargs) return cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))) # It a dummy real world use example: class test(Singleton_group): def __init__(self, salute): self.salute = salute a = test('bye') b = test('hi') c = test('bye') d = test('hi') e = test('goodbye') f = test('goodbye') id(a) 3070148780L id(b) 3070148908L id(c) 3070148780L b == d True b._Singleton_group__instances_args_dict {('test', ('bye',), '{}'): <__main__.test object at 0xb6fec0ac>, ('test', ('goodbye',), '{}'): <__main__.test object at 0xb6fec32c>, ('test', ('hi',), '{}'): <__main__.test object at 0xb6fec12c>} 

Hər bir obyekt tək elementli bir cache daşıyır ... Bu pis ola bilər, amma bəziləri üçün çox yaxşı işləyir :)

3
28 февр. Cavab Mychot tərəfindən verilir: ( 28 fevral. 2012-02-28 23:42 '12 saat 11:42 'da 2012-02-28 23:42
 class Singleton(object[,...]): staticVar1 = None staticVar2 = None def __init__(self): if self.__class__.staticVar1==None : # create class instance variable for instantiation of class # assign class instance variable values to class static variables else: # assign class static variable values to class instance variables 
2
cavab verildi 17 dekabr 2009-12-17 18:10 '09 at 18:10 2009-12-17 18:10

Singleton qardaşı

Mən tamamilə staale ilə razıyam və burada bir qardaşın yaranma nümunəsini buraxıram:

 class void:pass a = void(); a.__class__ = Singleton 

özü haqqında belə bir şey deyilsə belə özünü təkli olaraq eyni sinif hesab edir. Beləliklə, mürəkkəb siniflərdən istifadə edənlər biz onlarla bir çox olmadığı təqdirdə sona çatırlar.

Beləliklə, biz eyni təsirə sahib ola bilərik və dəyişən və ya modul kimi sadə məsələlərdən istifadə edə bilərik. Lakin, aydınlıq üçün dərslərdən istifadə etmək istəyirik və Pythonda bir sinif bir obyektdirsə , deməli, biz artıq bir obyektimiz var (heç bir nümunə yoxdur, amma eyni olacaq).

 class Singleton: def __new__(cls): raise AssertionError # Singletons can't have instances 

Bir nümunə hazırlamağa çalışsaq yaxşı bir iddia səhvimiz var və biz Statik üzvləri çıxışlara saxlaya bilərik və iş müddətində onlara dəyişiklik edə bilərik (Python'u sevirəm). Bu obyekt başqalarına qardaşların yarısı qədər yaxşıdır (isterseniz, hələ də yarada bilərsiniz), lakin sadəlik sayəsində daha sürətli olacaqdır.

2
11 янв. cavab verildi neu-rah Jan 11 2013-01-11 18:10 '13 at 18:10 2013-01-11 18:10

Mənim sadə həllim funksiya parametrlərinin default dəyərinə əsaslanır.

 def getSystemContext(contextObjList=[]): if len( contextObjList ) == 0: contextObjList.append( Context() ) pass return contextObjList[0] class Context(object): # Anything you want here 
2
28 нояб. Cavab 28 noyabr tarixində Tiezhenə verilmişdir. 2011-11-28 16:15 '11 'də saat 16:15' da 2011-11-28 16:15

Python üçün nisbətən daha yeni olan, mən ən ümumi deyim nə əmin deyiləm, amma düşünə biləcəyim ən sadə şey yalnız bir sinif yerinə bir modul istifadə edir. Sınıfınızdaki metodların bir örneği, modüldeki işlevleri yalnız haline getirecek ve hər hansı bir veri, sınıfın üyeleri değil, modülündeki değişkenler haline gelir. Mən şübhələnirəm ki, bu, tək insanların istifadə etdiyi problemin həlli üçün bir pyphonik yanaşmadır.

Həqiqətən, bir tək sinifdən istifadə etmək istəyirsinizsə, xüsusən Google-un ilk Singleton Python-da təsvir edilən həssas bir tətbiq var:

 class Singleton: __single = None def __init__( self ): if Singleton.__single: raise Singleton.__single Singleton.__single = self 

Bu bir oyun kimi səslənir.

2
28 авг. Cavab John 28 aug verilir . 2008-08-28 12:09 '08 at 12:09 pm 2008-08-28 12:09
 class Singeltone(type): instances = dict() def __call__(cls, *args, **kwargs): if cls.__name__ not in Singeltone.instances: Singeltone.instances[cls.__name__] = type.__call__(cls, *args, **kwargs) return Singeltone.instances[cls.__name__] class Test(object): __metaclass__ = Singeltone inst0 = Test() inst1 = Test() print(id(inst1) == id(inst0)) 
1
15 авг. Volodymyr Pavlenko tərəfindən verilən cavabı 15 av. 2012-08-15 10:08 '12 at 10:08 2012-08-15 10:08

Metaklasiyaya əsaslanan həllin daha yüksək olmasını istəmədiyiniz və bəzəkçiyə əsaslanan sadə bir yanaşmanı sevməyəcəyiniz hallarda (məsələn, bir elementli statik statik metodların işləməyəcəyi üçün) bu kompromis işləridir:

 class singleton(object): """Singleton decorator.""" def __init__(self, cls): self.__dict__['cls'] = cls instances = {} def __call__(self): if self.cls not in self.instances: self.instances[self.cls] = self.cls() return self.instances[self.cls] def __getattr__(self, attr): return getattr(self.__dict__['cls'], attr) def __setattr__(self, attr, value): return setattr(self.__dict__['cls'], attr, value) 
0
28 окт. cavab 28 oktyabr ithkuil verilir . 2011-10-28 12:52 '11 at 12:52 2011-10-28 12:52

haqqında digər suallar və ya bir sual