Python设计模式之单例模式实例
注:使用的是Python 2.7。
一个简单实现
class Foo(object):
__instance = None
def __init__(self):
pass
@classmethod
def getinstance(cls):
if(cls.__instance == None):
cls.__instance = Foo()
return cls.__instance
if __name__ == '__main__':
foo1 = Foo.getinstance()
foo2 = Foo.getinstance()
print id(foo1)
print id(foo2)
print id(Foo())
输出的前两个结果是相同的(id(foo1)与id(foo2)的值相同),第三个结果和前两个不同。这里类方法getinstance()用于获取单例,但是类本身也可以实例化,这样的方式其实并不符合单例模式的要求。但是这样做也有好处,代码简单,大家约定好这样子调用就行了。但是最好在类的命名上也体现了出来这是一个单例类,例如Foo_singleton。
换一个思路
先说一下init和new的区别:
class Foo(object):
__instance = None
def __init__(self):
print 'init'
if __name__ == '__main__':
foo = Foo()
运行结果是:
init
而下面的示例:
class Foo(object):
__instance = None
def __init__(self):
print 'init'
def __new__(cls, *args, **kwargs):
print 'new'
if __name__ == '__main__':
foo = Foo()
运行结果是:
new是一个类方法,会创建对象时调用。而init方法是在创建完对象后调用,对当前对象的实例做一些一些初始化,无返回值。如果重写了new而在new里面没有调用init或者没有返回实例,那么init将不起作用。以下内容引用自http://docs.python.org/2/reference/datamodel.html#object.new
If __new__() returns an instance of cls, then the new instance's __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().
If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked.
这样做:
class Foo(object):
__instance = None
def __init__(self):
print 'init'
def __new__(cls, *args, **kwargs):
print 'new'
if cls.__instance == None:
cls.__instance = cls.__new__(cls, *args, **kwargs)
return cls.__instance
if __name__ == '__main__':
foo = Foo()
错误如下:
RuntimeError: maximum recursion depth exceeded in cmp
而这样也有一样的错误:
class Foo(object):
__instance = None
def __init__(self):
if self.__class__.__instance == None:
self.__class__.__instance = Foo()
print 'init'
if __name__ == '__main__':
foo = Foo()
该怎么做呢?
下面参考了http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python/31887#31887:
class Foo(object):
__instance = None
def __new__(cls, *args, **kwargs):
print 'hhhhhhhhh'
if not cls.__instance:
cls.__instance = super(Foo, cls).__new__(cls, *args, **kwargs)
return cls.__instance
def hi(self):
print 'hi, world'
print 'hi, letian'
if __name__ == '__main__':
foo1 = Foo()
foo2 = Foo()
print id(foo1)
print id(foo2)
print isinstance(foo1, object)
print isinstance(foo1, Foo)
foo1.hi()
运行结果:
hhhhhhhhh
hhhhhhhhh
39578896
39578896
True
True
hi, world
hi, letian
那么,到底发生了什么,我们先回顾一下super:
>>> print super.__doc__
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
def meth(self, arg):
super(C, self).meth(arg)
可以肯定上面的单例模式代码中的这一行代码:
cls.__instance = super(Foo, cls).__new__(cls, *args, **kwargs)
super(Foo, cls)是object,super(Foo, cls).new方法使用的是object的new方法。我们看一下object.new方法的作用:
>>> print object.__new__.__doc__
T.__new__(S, ...) -> a new object with type S, a subtype of T
如果是一个继承链
class Fo(object):
def __new__(cls, *args, **kwargs):
print 'hi, i am Fo'
return super(Fo, cls).__new__(cls, *args, **kwargs)
class Foo(Fo):
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
print Foo is cls
print issubclass(cls, Fo)
print issubclass(cls, object)
cls.__instance = super(Foo, cls).__new__(cls, *args, **kwargs)
return cls.__instance
def hi(self):
print 'hi, world'
if __name__ == '__main__':
foo1 = Foo()
foo1.hi()
print isinstance(foo1, Foo)
print isinstance(foo1, Fo)
print isinstance(foo1, object)
运行结果如下:
True
True
True
hi, i am Fo
hi, world
True
True
True
如果如下定义Fo,也正常运行:
class Fo(object):
pass
但是,若这样定义:
class Fo(object):
def __new__(cls, *args, **kwargs):
print 'hi, i am Fo'
运行时报错如下:
AttributeError: 'NoneType' object has no attribute 'hi'

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











PHP terutamanya pengaturcaraan prosedur, tetapi juga menyokong pengaturcaraan berorientasikan objek (OOP); Python menyokong pelbagai paradigma, termasuk pengaturcaraan OOP, fungsional dan prosedur. PHP sesuai untuk pembangunan web, dan Python sesuai untuk pelbagai aplikasi seperti analisis data dan pembelajaran mesin.

PHP sesuai untuk pembangunan web dan prototaip pesat, dan Python sesuai untuk sains data dan pembelajaran mesin. 1.Php digunakan untuk pembangunan web dinamik, dengan sintaks mudah dan sesuai untuk pembangunan pesat. 2. Python mempunyai sintaks ringkas, sesuai untuk pelbagai bidang, dan mempunyai ekosistem perpustakaan yang kuat.

PHP berasal pada tahun 1994 dan dibangunkan oleh Rasmuslerdorf. Ia pada asalnya digunakan untuk mengesan pelawat laman web dan secara beransur-ansur berkembang menjadi bahasa skrip sisi pelayan dan digunakan secara meluas dalam pembangunan web. Python telah dibangunkan oleh Guidovan Rossum pada akhir 1980 -an dan pertama kali dikeluarkan pada tahun 1991. Ia menekankan kebolehbacaan dan kesederhanaan kod, dan sesuai untuk pengkomputeran saintifik, analisis data dan bidang lain.

Python lebih sesuai untuk pemula, dengan lengkung pembelajaran yang lancar dan sintaks ringkas; JavaScript sesuai untuk pembangunan front-end, dengan lengkung pembelajaran yang curam dan sintaks yang fleksibel. 1. Sintaks Python adalah intuitif dan sesuai untuk sains data dan pembangunan back-end. 2. JavaScript adalah fleksibel dan digunakan secara meluas dalam pengaturcaraan depan dan pelayan.

Untuk menjalankan kod python dalam teks luhur, anda perlu memasang plug-in python terlebih dahulu, kemudian buat fail .py dan tulis kod itu, dan akhirnya tekan Ctrl B untuk menjalankan kod, dan output akan dipaparkan dalam konsol.

Kod penulisan dalam Kod Visual Studio (VSCode) adalah mudah dan mudah digunakan. Hanya pasang VSCode, buat projek, pilih bahasa, buat fail, tulis kod, simpan dan jalankannya. Kelebihan vscode termasuk sumber lintas platform, bebas dan terbuka, ciri-ciri yang kuat, sambungan yang kaya, dan ringan dan cepat.

Kod VS boleh digunakan untuk menulis Python dan menyediakan banyak ciri yang menjadikannya alat yang ideal untuk membangunkan aplikasi python. Ia membolehkan pengguna untuk: memasang sambungan python untuk mendapatkan fungsi seperti penyempurnaan kod, penonjolan sintaks, dan debugging. Gunakan debugger untuk mengesan kod langkah demi langkah, cari dan selesaikan kesilapan. Mengintegrasikan Git untuk Kawalan Versi. Gunakan alat pemformatan kod untuk mengekalkan konsistensi kod. Gunakan alat linting untuk melihat masalah yang berpotensi lebih awal.

Running Python Code di Notepad memerlukan Python Executable dan NPPExec plug-in untuk dipasang. Selepas memasang Python dan menambahkan laluannya, konfigurasikan perintah "python" dan parameter "{current_directory} {file_name}" dalam plug-in nppexec untuk menjalankan kod python melalui kunci pintasan "f6" dalam notepad.
