Rumah > Artikel > pembangunan bahagian belakang > Lima cara untuk menulis mod tunggal dalam Python
Singleton Pattern ialah corak reka bentuk perisian yang biasa digunakan Tujuan utama corak ini adalah untuk memastikan bahawa hanya satu contoh kelas tertentu wujud. Objek singleton berguna apabila anda mahu hanya satu contoh kelas tertentu muncul dalam keseluruhan sistem.
Sebagai contoh, maklumat konfigurasi program pelayan disimpan dalam fail dan pelanggan membaca maklumat fail konfigurasi melalui kelas AppConfig. Jika semasa menjalankan program, kandungan fail konfigurasi perlu digunakan di banyak tempat, iaitu, contoh objek AppConfig perlu dibuat di banyak tempat, ini akan membawa kepada kewujudan berbilang contoh AppConfig objek dalam sistem, yang akan membazirkan sumber memori, terutamanya jika fail konfigurasi mengandungi banyak kandungan.
Malah, untuk kelas seperti AppConfig, kami berharap hanya satu objek contoh akan wujud semasa program dijalankan.
Dalam Python, kita boleh menggunakan pelbagai kaedah untuk melaksanakan corak tunggal:
Perincian berikut pengenalan:
Malah, modul Python adalah mod tunggal semula jadi, kerana apabila modul diimport buat kali pertama, fail .pyc akan dihasilkan . Apabila diimport untuk kali kedua, fail .pyc akan dimuatkan terus tanpa melaksanakan kod modul sekali lagi.
Oleh itu, kita hanya perlu mentakrifkan fungsi dan data yang berkaitan dalam modul untuk mendapatkan objek tunggal.
Jika kami benar-benar mahukan kelas tunggal, kami boleh mempertimbangkan untuk melakukan ini:
class Singleton(object): def foo(self): pass singleton = Singleton()
Simpan kod di atas dalam fail mysingleton.py Apabila anda ingin menggunakannya, terus masuk Import objek dalam fail ini daripada fail lain. Objek ini ialah objek mod tunggal
from mysingleton import singleton
def Singleton(cls): _instance = {} def _singleton(*args, **kargs): if cls not in _instance: _instance[cls] = cls(*args, **kargs) return _instance[cls] return _singleton @Singleton class A(object): a = 1 def __init__(self, x=0): self.x = x a1 = A(2) a2 = A(3)
class Singleton(object): def __init__(self): pass @classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance
Secara amnya, semua orang berpendapat bahawa ini melengkapkan mod tunggal, tetapi akan ada masalah apabila menggunakan multi-threading:
class Singleton(object): def __init__(self): pass @classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance import threading def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start()
Selepas program dilaksanakan, hasil cetakan adalah seperti berikut:
<__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0> <__main__.Singleton object at 0x02C933D0>
Lihat Tiada masalah, tetapi ia adalah kerana kelajuan pelaksanaan terlalu cepat Jika terdapat beberapa operasi IO dalam kaedah __init__, anda akan mendapati masalahnya.
Di bawah kami mensimulasikan melalui time.sleep Kami menambah kod berikut pada kaedah __init__ di atas:
def __init__(self): import time time.sleep(1)
Selepas melaksanakan semula program, hasilnya adalah seperti berikut:
<__main__.Singleton object at 0x034A3410> <__main__.Singleton object at 0x034BB990> <__main__.Singleton object at 0x034BB910> <__main__.Singleton object at 0x034ADED0> <__main__.Singleton object at 0x034E6BD0> <__main__.Singleton object at 0x034E6C10> <__main__.Singleton object at 0x034E6B90> <__main__.Singleton object at 0x034BBA30> <__main__.Singleton object at 0x034F6B90> <__main__.Singleton object at 0x034E6A90>Timbul masalah! Singleton yang dibuat dengan cara di atas tidak boleh menyokong multi-threading.
import time import threading class Singleton(object): _instance_lock = threading.Lock() def __init__(self): time.sleep(1) @classmethod def instance(cls, *args, **kwargs): with Singleton._instance_lock: if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start() time.sleep(20) obj = Singleton.instance() print(obj)Hasil cetakan adalah seperti berikut:
<__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110> <__main__.Singleton object at 0x02D6B110>Ini hampir sama, tetapi masih terdapat masalah kecil, iaitu, apabila program dijalankan, selepas masa.sleep(20 ) dilaksanakan, objek diwujudkan di bawah , ia sudah berada dalam mod tunggal.
@classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): with Singleton._instance_lock: if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instanceDengan cara ini, seseorang boleh menyokong berbilang rangkaian. Mod tunggal telah selesai. +
import time import threading class Singleton(object): _instance_lock = threading.Lock() def __init__(self): time.sleep(1) @classmethod def instance(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): with Singleton._instance_lock: if not hasattr(Singleton, "_instance"): Singleton._instance = Singleton(*args, **kwargs) return Singleton._instance def task(arg): obj = Singleton.instance() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start() time.sleep(20) obj = Singleton.instance() print(obj)Mod tunggal yang dilaksanakan dengan cara ini mempunyai sekatan penggunaan kemudiannya mesti dilakukan melalui obj = Singleton.instance()
import threading class Singleton(object): _instance_lock = threading.Lock() def __init__(self): pass def __new__(cls, *args, **kwargs): if not hasattr(Singleton, "_instance"): with Singleton._instance_lock: if not hasattr(Singleton, "_instance"): Singleton._instance = object.__new__(cls) return Singleton._instance obj1 = Singleton() obj2 = Singleton() print(obj1,obj2) def task(arg): obj = Singleton() print(obj) for i in range(10): t = threading.Thread(target=task,args=[i,]) t.start()Hasil cetakan adalah seperti berikut:
<__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0> <__main__.Singleton object at 0x038B33D0>Menggunakan mod singleton ini, apabila membuat instantiation objek pada masa hadapan, kaedah instantiating objek adalah sama seperti biasa obj = Singleton() .
例子: class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): pass obj = Foo() # 执行type的 __call__ 方法,调用 Foo类(是type的对象)的 __new__方法,用于创建对象,然后调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。 obj()# 执行Foo的 __call__ 方法
class SingletonType(type): def __init__(self,*args,**kwargs): super(SingletonType,self).__init__(*args,**kwargs) def __call__(cls, *args, **kwargs): # 这里的cls,即Foo类 print('cls',cls) obj = cls.__new__(cls,*args, **kwargs) cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj) return obj class Foo(metaclass=SingletonType): # 指定创建Foo的type为SingletonType def __init__(self,name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls) obj = Foo('xx')Melaksanakan mod tunggal:
import threading class SingletonType(type): _instance_lock = threading.Lock() def __call__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): with SingletonType._instance_lock: if not hasattr(cls, "_instance"): cls._instance = super(SingletonType,cls).__call__(*args, **kwargs) return cls._instance class Foo(metaclass=SingletonType): def __init__(self,name): self.name = name obj1 = Foo('name') obj2 = Foo('name') print(obj1,obj2)
Atas ialah kandungan terperinci Lima cara untuk menulis mod tunggal dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!