class Singleton(object):
def __new__(cls):
# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
class si():
class_arg='a'
def __init__(self):
self.obj='b'
self.class_arg='c'
@classmethod
def a(cls):
return 1
def b(self):
return 2
obj0=Singleton
obj1 = Singleton()
obj2 = Singleton()
obj3=si()
obj4=si()
obj5=si
Python定义的一个类,占有一个唯一的内存地址。
正常情况下,对类进行实例化的时候,每实例化一次,会生成一个新的对象(对应一个新的内存地址)
因此,obj3,obj4,obj5是三个不同的地址(obj3\obj4的类型是对象,obj5的类型是类)
对象会继承类的方法,但是类不能使用对象的方法,在si中,a是类的方法,b是对象的方法
因此obj3\obj4可以执行a,b,obj5只能执行a
obj5如果要执行b,则需要传参一个对象.obj5.b(ojb3)
###################我觉得可能是因为,类调用类方法的时候,第一个入参是这个类,对象调用对象的方法的时候,第一个入参是这个对象,
对象调用类的方法时,第一个入参是对象继承的类
类调用对象的方法时,不自动具备第一个入参(对象),因此需主动传入一个对象
class_arg是类的属性,obj是对象的属性,对象的class_arg属性被改写成c
所以,__init__方法是对对象进行初始化
而__new__是对类进行初始化,生成一个新的对象,作为__init__的self
在类Singleton中,重写__new__,不再返回一个新的对象,而是返回一个类的属性,那么每次构造类Singleton的对象时,不再生成一个新的对象(新的内存地址),
而是获取类的instance属性地址,因此obj1和obj2是同一个内存地址,但是跟obj0不是一个地址
若将Singleton改为
def __new__(cls):
# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls
即对类初始化后直接返回类,则 obj0/obj1/obj2是同一个内存地址(都指向定义的类)