Python实现单例类

有时候需要像Java一样一个类只允许其生成一个类实例。比如设计一个打印机程序,一台计算机可以连接若干台打印机,但是同一份文件只允许一台打印机输出,避免重复打印。

Java实现单例的最简单方法:

public class PrintProgrammer:
{
    private static PrintProgrammer SingleTo = null;

    private void PrinterProgrammer() {}

    public static getInstance(){
        if (SingleTo == null) {
            SingleTo = new PrinterProgrammer()
        }
        return SingleTo
    }
}

其实Java的单例说白了很简单,就是把构造方法的权限设置为private,这样只有在类内才能访问,外界无法进行更改。然后用public静态方法进行判断是否已经有了类实例。

那么问题来了,Python没有Java的这种访问权限:public、protected、default、private!就无法实现单例模式了吗?当然不是的,类似Python这种动态语言,本身隐藏了很多实现细节,有些“高级”的类方法不是没有,而是不常有。

我们都知道Python是在特殊方法__init__中生成实例属性的,但实际上调用__init__方法之前实例已经生成了,这就是__new__方法。当生成实例的时候,__new__方法最先被调用,然后才是__init__方法。

__new__特殊方法第一个形参是cls,是类本身,而不是self(实例)。它必须有return值,这个返回值就是类的实例,返回给__init__的第一个参数,现在知道为什么__init__方法的第一个参数是self了吧。

class MyCls(object):
    def __new__(cls, name, age):
        print "__new__ method, name: {0} age:{1}\r\n".format(name, age)
        return super(MyCls, cls).__new__(cls, name, age)

    def __init__(self, name, age):
        self.name = name 
        self.age = age
        print "__init__ calling"

i = MyCls("bob", 22)

>>> __new__ metho, name: bob age:22

>>> __init__ calling

如果我们要继承一些内置的不可变的类,对其进行一些更改,比如说把传入的signed 类型(当然这是C中的叫法)初始化成unsigned类型。

class MInt(int, object):
    def __init__(self, num):
        super(MInt, self).__init__(abs(num))

i = MInt(-9)
>>> -9

我们发现并没有什么卵用,这时候就应该使用__new__方法对其进行初始化。

class MInt(int):
    def __new__(cls, num):
        return super(MInt, cls).__new__(cls, abs(num))

i = MInt(-9)
print i
>>> 9

Note:__new__方法一定要return,因为这是返回类的实例。

下面我们利用它来模拟Java中的单例:

class CLS(object):
    def __init__(self, num):
        self.num = num

    def __new__(cls, num):
        if not hasattr(cls, "instance"):
            cls.instance = super(CLS, cls).__new__(cls)
        return cls.instance

a = CLS(9)
b = CLS(10)

print a
print b
print CLS.instance

print a.num
print b.num

print a is b is CLS.instance

>>> <__main__.CLS object at 0x02C03290>
>>> <__main__.CLS object at 0x02C03290>
>>> <__main__.CLS object at 0x02C03290>
>>> 10
>>> 10
>>> True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值