用单例模式实现网站计数器(Python如何实现单例模式)

本文目录
Python如何实现单例模式
有些时候你的项目中难免需要一些全局唯一的对象,这些对象大多是一些工具性的东西,在Python中实现单例模式并不是什么难事。以下总结几种方法:
使用类装饰器
使用装饰器实现单例类的时候,类本身并不知道自己是单例的,所以写代码的人可以不care这个,只要正常写自己的类的实现就可以,类的单例有装饰器保证。
def singleton(cls):
instances = {}
def _wrapper(*args, **kwargs):
if cls not in instances:
instances = cls(*args, **kwargs)
return instances
return _wrapper
你会发现singleton装饰器内部使用了一个dict。当然你也可以用其他的方式,不过以下的实现是错误的:
def singleton(cls):
_instance = None #外部作用域的引用对于嵌套的内部作用域是只读的
def _wrapper(*args, **kwargs):
if _instance is None: #解释器会抛出"UnboundLocalError: ...referenced before assignment"
_instance = cls(*args, **kwargs) #赋值行为使解释器将"_instance"看作局部变量
return _instance
return _wrapper
使用元类(__metaclass__)和可调用对象(__call__)
Python的对象系统中一些皆对象,类也不例外,可以称之为”类型对象”,比较绕,但仔细思考也不难:类本身也是一种对象,只不过这种对象很特殊,它表示某一种类型。是对象,那必然是实例化来的,那么谁实例化后是这种类型对象呢?也就是元类。
Python中,class关键字表示定义一个类对象,此时解释器会按一定规则寻找__metaclass__,如果找到了,就调用对应的元类实现来实例化该类对象;没找到,就会调用type元类来实例化该类对象。
__call__是Python的魔术方法,Python的面向对象是”Duck type”的,意味着对象的行为可以通过实现协议来实现,可以看作是一种特殊的接口形式。某个类实现了__call__方法意味着该类的对象是可调用的,可以想像函数调用的样子。再考虑一下foo=Foo()这种实例化的形式,是不是很像啊。结合元类的概念,可以看出,Foo类是单例的,则在调用Foo()的时候每次都返回了同样的对象。而Foo作为一个类对象是单例的,意味着它的类(即生成它的元类)是实现了__call__方法的。所以可以如下实现:
class Singleton(type):
def __init__(cls, name, bases, attrs):
super(Singleton, cls).__init__(name, bases, attrs)
cls._instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None
# 以下不要使用’cls._instance = cls(*args, **kwargs)’, 防止死循环,
# cls的调用行为已经被当前’__call__’协议拦截了
# 使用super(Singleton, cls).__call__来生成cls的实例
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance
class Foo(object): #单例类
__metaclass__ = Singleton
》》》a = Foo()
》》》b = Foo()
》》》a is b
》》》True
》》》a.x = 1
》》》b.x
》》》1
使用__new__
__init__不是Python对象的构造方法,__init__只负责初始化实例对象,在调用__init__方法之前,会首先调用__new__方法生成对象,可以认为__new__方法充当了构造方法的角色。所以可以在__new__中加以控制,使得某个类只生成唯一对象。具体实现时可以实现一个父类,重载__new__方法,单例类只需要继承这个父类就好。
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, ’_instance’):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
class Foo(Singleton): #单例类
a = 1
单例模式的实现方式
几种常见的方法:
- **饿汉式**:这种实现方式在类加载时就完成了实例化,因此也被称为“提前实例化”或“饿汉式”。这种实现方式的好处是,一旦类加载完成,实例就被创建并存储在内存中,后续的请求都会直接返回这个实例,不需要再进行额外的实例化操作。 ```python class Singleton: **代码示例** ``` 在上面的代码中,Singleton类的静态变量__instance初始化为None。每次尝试创建新实例时都会检查__instance是否已经存在实例。
- **懒汉式**:这种实现方式在需要使用单例时才创建实例。这种实现方式的缺点是存在线程安全问题,因为多个线程可能同时尝试创建实例。为了解决这个问题,我们可以使用synchronized关键字或者使用线程局部变量来实现线程安全。 ```python class Singleton: **代码示例** ``` 在上面的代码中,我们使用了synchronized关键字来确保只有一个线程可以创建实例。
- **静态内部类**:这是另一种常见的单例模式实现方式。通过将单例对象封装在一个静态内部类中,我们可以确保只有一个实例被创建。这种方式的好处是简单易用,并且可以轻松地支持多线程环境。 ```python class Singleton: **代码示例** ``` 在上面的代码中,我们使用了一个静态内部类来封装单例对象。
什么是单例模式希望有个运用单例模式的类的例子
单例模式可以说是GOF设计模式中最为简单的模式,也是背负骂名最多的模式。不过一直以来,我对许多类似关于它是最烂和反模式的评价却不尽以为然。
模式本身很简单,除了牵涉多线程安全问题引起的一点罗唆外。所以,我不太想讨论GOF提供的关于该模式的参考实现。我所关注的是它背后带来的对问题的看法和思考方式。
我们先看看单例模式出现的背景很存在的意义。单例模式通俗来讲就是确保类只有一个实例。那么好,我们问一下,为什么要确保类只有一个实例呢?其实无非是两个方面的作用:一、想控制资源的使用,它又体现在两个方面,其中之一是控制实例数目的产生来节约资源,其二通过线程同步控制资源的并发访问;二、想作为一种通信媒介,在不建立直接关联的条件下让不相关的两个程序进行通信,尤其是多线程。第二点,我说的有些抽象,简单讲吧,就类似于大家基于一个黑板讨论东西,而不关心参与讨论的对象。单例就取了黑板的作用。

更多文章:
电脑里2个系统怎么删除一个(电脑开机显示有两个系统,如何删除一个)
2026年9月7日 12:20
scrollthrough意思(“scroll”是什么意思)
2026年9月7日 08:00
怎么激活keygen(注册机如何激活cad2008一个简单激活cad2008的方法)
2026年9月7日 06:30
vba编写excel插件(excel vba中能否动态创建控件)
2026年9月7日 04:40
为什么控件属性点不了(c#引用的第三方控件,属性全部显示为灰色,属性值不可更改)
2026年9月7日 03:50
旅游网站设计思路和主要设计内容(旅游网站建设方案该如何进行设计)
2026年9月7日 01:50
野生菌十大名菌野生菌十大名菌分别是哪些?菌内有几种野生菌 野生的鸡枞菌是什么样子
2026年9月6日 23:50




