类的内置方法和单例模式
一、什么是类的内置方法?
凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法。
类的内置方法,会在某种条件满足下自动触发。
内置方法如下:
__new__: 在__init__触发前,自动触发。 调用该类时,内部会通过__new__产生一个新的对象。
__init__: 在调用类时自动触发。 通过产生的对象自动调用__init__()
class Demo: ## 条件: __init__: 在调用类时自动触发。 def __init__(self): print('此处是__init__方法的执行') ## 1、条件: __new__: 在__init__触发前,自动触发。 def __new__(cls, *args, **kwargs): print('此处是__new__方法的执行') ## python内部通过object调用内部的__new__实现产生一个空的对象 ---> 内存地址 return object.__new__(cls, *args, **kwargs) obj = Demo() #此处是__new__方法的执行 #此处是__init__方法的执行 #类内部的方法无关位置
#2、__getattr__: 在 “对象.属性” 获取属性时,若 “属性没有” 时触发。 def __getattr__(self, item): print('此处是__getattr__方法的执行') print(item) # x return '想要返回的值' obj = Demo() obj.x #属性x 此时不存在 #结果:此处是__getattr__方法的执行 x print(obj.x) #结果:想要返回的值
#3、条件: __getattribute__: 在 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发。 def __getattribute__(self, item): print('此处是__getattribute__方法的执行') # print(item) #x return 'z' obj = Demo() # obj.x #结果: 此处是__getattribute__方法的执行 x print(obj.x) #z ##注意: 只要__getattr__ 与 __getattribute__ 同时存在类的内部,只会触发__getattribute__。
# 4、条件: 当 “对象.属性 = 属性值” , 添加或修改属性时触发
def __setattr__(self, key, value):
print('此处是__setattr__方法的执行')
# print(key, value)
print(self.__dict__) #{}
self.__dict__[key] = value #obj.x = 10
print(self.__dict__) #{'x': 10}
obj = Demo()
obj.x = 10
##5、条件: 在调用对象 “对象 + ()” 时触发。 def __call__(self, *args, **kwargs): print('此处是__call__方法的执行') return 123 obj = Demo() obj() #此处是__call__方法的执行
##6、条件: 在打印对象时触发。该方法必须要有一个 “字符串” 返回值。 def __str__(self): print('此处是__str__方法的执行') return '1' obj = Demo() print(obj) #此处是__str__方法的执行 #1
##7、在对象通过 “对象[key]” 获取属性时触发。 def __getitem__(self, item): print('此处是__getitem__方法的执行') print(item) return self.__dict__[item] obj = Demo() obj['x'] print(obj['x']) #KeyError: 'x'
##8、在对象通过 “对象[key]=value值” 设置属性时触发。 def __setitem__(self, key, value): print('此处是__setitem__方法的执行') # print(key, value) self.__dict__[key] = value obj = Demo() obj['x'] = 20 print(obj.x) #此处是__setitem__方法的执行 #20
二、单例
指的是在确定类中的属性与方法不变时,需要反复调用该类,产生不同的对象,会产生不同的内存地址,造成资源浪费。
让所有类在实例化时,指向同一个内存地址,称之为单例模式。
单例的优点:
节省内存空间。
方式一:通过@classmethod实现
class MySQL: tag = None def __init__(self, x, y): self.x = x self.y = y @classmethod def singleton(cls, x, y): # 单例方法 ---》 类方法 ## 判断tag中若没有值,证明没有对象 if not cls.tag: ## 产生一个对象并返回 obj = cls(x, y) ## None ---> obj cls.tag = obj # 若tag中有值,证明对象已经存在,则直接返回该对象 return cls.tag def start_mysql(self): print('启动mysql') def close(self): print('关闭mysql') #调用类的方法 obj1 = MySQL.singleton(10, 20) print(obj1) #<__main__.MySQL object at 0x00000000029B1CF8> obj2 = MySQL.singleton(10, 20) print(obj2) #<__main__.MySQL object at 0x00000000029B1CF8>
方式二:通过__new__实现:
class Singleton: __instance = None def __new__(cls, *args, **kwargs): if not cls.__instance: #造一个空对象 cls.__instance = object.__new__(cls) return cls.__instance obj1 = Singleton() obj2 = Singleton() obj3 = Singleton() print(obj1) print(obj2) print(obj3)