Python学习笔记-元类和单例

元类

一切皆对象,一切都有类型;

class和type本质上没有什么不同;

类也是对象,类型是type;

就像对象是类的实例一样,类是它元类的实例,调用元类可以创建类

# 一般的类定义
class Student:
    type = 'STU'
# 底层利用type实现,调用元类创建类
Student = type('Student',(object,),{'type':'STU'})   # 类type是类Student的类,是元类
# 生成对象
s = Student()

确切的说,当你 创建 一个类时,解释器会调用默认或指定的元类来生成它;此时我们可以借助元类来实现一些动作,譬如拦截类的创建,修改类以及其他动作

# 利用元类实现更改类中元素的值
# 定义一个元类Metaclass
class Metaclass(type):  # *args返回的元组内容为(类名,父类,dict(属性和方法))
    def __new__(cls, *args, **kwargs):  # 创建时调用
        if 'c' in args[2]:              # 判断属性中有无属性名为c的
            args[2]['c']='Exchange'     # 将属性c的值改为Exchange
        return type.__new__(cls,*args)  # 返回
# 定义一个类,继承自object,元类时Metaclass
class UseMeta(object,metaclass=Metaclass):
    a = 123
    c = 456
    pass
um = UseMeta()
print(um.a)
print(um.c)   # 此时c的值已经从123被改为了Exchange
==================================
123
Exchange

单例

单例是一种 设计模式,应用该模式的类只会生成一个实例。避免产生冲突,节省内存空间

单例模式保证了在程序的不同位置都可以且仅可以取到同一个对象实例;

如果不存在则创建,存在则返回

# 应用单例的设计模式
class ManageTool:       # 对该类应用单例设计模式
    __instance = None   # 私有类属性,保存地址
    def __new__(cls,*args,**kwargs):
        if cls.__instance is None:  # 检查是否是空值
            cls.__instance = object.__new__(cls,*args,**kwargs)  # 是空值,调用object新建
        return cls.__instance  # 返回地址
# 检查地址是空值则创建,不是空值则直接返回,保证了都是同一个地址
mt1 = ManageTool()
mt2 = ManageTool()
mt3 = ManageTool()
print(id(mt1))   # 输出地址检查效果
print(id(mt2))
print(id(mt3))
==============================
2211180304144
2211180304144
2211180304144

利用装饰器实现单例:

# 定义类装饰器,通过类装饰器实现
class cls_dec:
    def __init__(self,cls):   
        self.cls = cls         # cls传入的是被装饰的类
        self.__instance = {}   # 定义一个字典用来保存地址
    def __call__(self,*args,**kwargs):
        if self.cls not in self.__instance:  # 判断地址是否在容器中
            self.__instance[self.cls] = self.cls()  # 不在容器中,进行创建和赋值
        return self.__instance[self.cls]   # 返回结果
# 定义函数装饰器,通过函数装饰器实现
def func_dec(cls):
    _instance = {}     # 定义一个字典用来存放地址
    def wrapper(*args,**kwargs):
        if cls not in _instance:    # 判断地址是否在容器中
            _instance[cls] = cls()  # 不在容器中,进行创建和赋值
        return _instance[cls]       # 返回结果
    return wrapper                  # 返回内层函数

@cls_dec   # 利用装饰器装饰,函数装饰器或类装饰器均可
class Singleton:
    def __init__(self):
        print('Singleton init')
sl1 = Singleton()
sl2 = Singleton()
print(id(sl1))
print(id(sl2))
=================================
Singleton init   # 仅进行了一次初始化
2654923708512
2654923708512

利用元类实现单例:

# 定义一个元类
class Singleton(type):
    # 重写call方法,使其能够实现单例的功能
    def __call__(cls,*args,**kwargs):
        if not hasattr(cls,'_instance'):
            cls._instance = super().__call__(*args,**kwargs)
        return cls._instance
# 利用元类进行创建,具有了单例的效果
class Cls(metaclass = Singleton):
    pass
cls1 = Cls()
cls2 = Cls()
print(id(cls1))
print(id(cls2))
========================
2339953628944
2339953628944
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值