类的内置方法(魔法方法)
一、类的内置方法
- 什么是类的内置方法
- 凡是在类内部定义,以
__
开头__
结尾的方法,都是类的内置方法,也称之为魔法方法 - 类的内置方法,会在某种条件满足下自动触发
- 凡是在类内部定义,以
内置方法如下
__new__
:在__init__
触发前,自动触发。- 调用该类时,内部会通过
__new__
产生一个新的对象
- 调用该类时,内部会通过
class Demo(object):
# 条件: __new__:在__init__触发前,自动触发
def __new__(cls, *args, **kwargs):
print('此处是__new__方法的执行')
# python 内部通过object调用内部的__new__实现产生一个空的对象——>内存地址
return object.__new__(cls, *args, **kwargs)
__init__
:在调用类时自动触发。- 通过产生的对象自动调用
__init__
()
- 通过产生的对象自动调用
# 条件:__init__:在调用类时自动触发
def __init__(self):
print('此处是__init__方法的执行')
demo_obj = Demo()
此处是__init__方法的执行
__getattr__
:在"对象 . 属性"获取属性时,若"属性没有"时触发
def __getattr__(self, item):
print('此处是__getattr__方法的执行')
print(item)
#return '想要返回的值'
return '自定义的值'
demo_obj = Demo() # x
print(demo_obj.x) # 自定义的值
__getattribute__
:在"对象 . 属性"获取属性时,无论"属性有没有"都会触发
def __getattribute__(self, item):
print(item)
# print(self.__dict__)
# return self.__dict__[item]
# 注意:此处不能通过"对象.属性",否则会产生递归调用,程序崩溃
# getattr:内部调用了————> __getattribute__
return (self, item)
注意:只要__getattr__
与__getattribute__
同时存在类的内部,只会触发后者
__setattr__
当"对象 . 属性 = 属性值", 添加或修改属性时触发
def __setattr__(self, key, value):
print('此处是__setattr__方法的执行')
print(key, value)
# 出现递归
# self.key = value
# print(self.__dict__)
# 此处是对 对象的名称空间——> 字典进行操作
self.__dict__[key] = value
demo_obj = Demo() # 此处是__setattr__方法的执行
demo_obj.x = 10 # x 10
print(demo_obj.x) # 10
__call__
在调用对象"对象+()"时触发
def __call__(self, *args, **kwargs):
print('此处是__call__方法的执行')
# 调用对象时返回的值
return [1, 2, 3, 4, 5]
demo_obj = Demo()
res = demo_obj() # 此处是__call__方法的执行
print(res) # [1, 2, 3, 4, 5]
print(demo_obj) # <__main__.Demo object at 0x0000028DB3DA7B38>
__str__
在打印对象时触发
def __str__(self):
print('此处是__str__方法的执行')
return '111'
demo_obj = Demo()
print(demo_obj)
此处是__str__方法的执行
111
注意:该方法必须要有一个“字符串”返回值
__getitem__
在对象通过“对象[key]”获取属性时触发
def __getitem__(self, item):
print('此处是__getitem__方法的执行')
print(item)
return self.__dict__[item]
print(demo_obj['x'])
print(demo_obj['y'])
x
10
y
20
__setitem__
在对象通过“对象[key] = value值”设置属性时触发
def __setitem__(self, key, value):
print('此处是__setitem__方法的执行')
print(key, value)
# print(self.__dict__)
# self.key = value # {'key': value}
# print(self.__dict__)
self.__dict__[key] = value
demo_obj['y'] = 300
print(demo_obj.y)
此处是__setitem__方法的执行
y 300
300
二、单例模式
- 什么是单例模式
- 单例模式指的是在确定“类中的属性与方法”不变时,需要反复调用该类,产生不同的对象,会产生不同的内存地址,造成资源的浪费
- 让所有类在实例化时,指向同一个内存地址,称之为单例模式
- 无论产生多个对象,都会指向 单个 实例
- 单例的优点
- 节省内存空间
class Foo:
def __init__(self, x, y):
self.x = x
self.y = y
foo_obj1 = Foo(10, 20)
print(foo_obj1.__dict__) # {'x': 10, 'y': 20}
print(foo_obj1) # <__main__.Foo object at 0x000002085EF77B38>
foo_obj2 = Foo(10, 20)
print(foo_obj2.__dict__) # {'x': 10, 'y': 20}
print(foo_obj2) # <__main__.Foo object at 0x000002085EF77D30>
这里就出现了重复调用类时,会产生不同内存地址的对象,造成资源浪费
- 通过classmethod实现单例
import settings
# 通过 classmethod
class MySQL:
# 一个默认值,用于判断对象是否存在,对象不存在证明值是None
# __instance = None
__instance = None
def __init__(self, host, port):
self.host = host
self.port = port
@classmethod
def singleton(cls, host, port):
# 判断__instance中若没有值,证明没有对象
if not cls.__instance:
# 产生一个对象并返回
obj = cls(host, port)
# None ---> obj
cls.__instance = obj
# 若__instance中有值,证明对象已经存在,则直接返回该对象
return cls.__instance
def start_mysql(self):
print('启动mysql...')
def close(self):55555555
print('关闭mysql...')
obj1 = MySQL.singleton(settings.HOST, settings.PORT)
print(obj1)
obj2 = MySQL.singleton(settings.HOST, settings.PORT)
print(obj2)
obj3 = MySQL.singleton(settings.HOST, settings.PORT)
print(obj3)
这样产生的对象会指向同一个内存地址,会节省内存空间
<__main__.MySQL object at 0x00000133FFB1F588>
<__main__.MySQL object at 0x00000133FFB1F588>
<__main__.MySQL object at 0x00000133FFB1F588>
- 通过
__new__
实现单例
# __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()
print(obj1)
print(obj2)
- 通过装饰器实现单例
def singleton(cls):
_instance = {}
def inner(*args, **kwargs):
if cls not in _instance:
obj = cls(*args, **kwargs)
_instance[cls] = obj
return _instance[cls]
return inner
@singleton
class Father:
pass
obj1 = Father()
obj2 = Father()
print(obj1)
print(obj2)
- 通过导入模块实现单例
# 另写模块 SingletonCls
class SingletonCls:
pass
obj = SingletonCls()
from Singleton import obj
print(obj)
from Singleton import obj
print(obj)
from Singleton import obj
print(obj)