元类介绍

一切源自于一句话:python中一切皆为对象。既然如此类是不是也是对象呢?
所有的对象都是实例化类得到的,类也是对象,
那么类是怎么得到的呢?类是由于元类实例化得到的.
创建类的流程分析
class关键字在帮我们创建类时,必然帮我们调用了元类Teacher=type(...),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是
1、类名class_name='Teacher'
2、基类们class_bases=(object,)
3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的
调用type时会依次传入以上三个参数
自己来实例化一个类
 
class_name = "Teacher"
class_body = """
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def say(self):
        print('%s says welcome to the Beijing' %self.name)
"""
class_dict = exce(class_body)
bases = (object,)
Teacher = type(class_name,class_body,bases)
 
综上,class关键字帮我们创建一个类应该细分为以下四个过程
1.获取类名
2.获取基类
3.获取名称空间
4.实例化元类得到类

补充__call__函数得执行时机

该方法会在调用对象是自动触发执行 (对象加括号)
 
class Foo:
    def __call__(self, *args, **kwargs):
        print("run")
f = Foo()
f()
 

自定义元类控制类的创建

一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元类
 
 
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    pass
class Teacher(object,metaclass=Mymeta): # Teacher=Mymeta('Teacher',(object),{...})
    school='tsinghua'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def say(self):
        print('%s says welcome to the Beijing' %self.name)
 
需求 
1.规范类名必须大写
2.类中必须包含文档注释
 
class MyMate(type):
    def __init__(self,name,bases,dic):
        print("run")
        if not dic.get("__doc__"):
            raise TypeError("类必须有文档注释!")
        if not name.istitle():
            raise TypeError("类名必须大写开头!")
        super().__init__(name,bases,dic)
class Foo(object,metaclass=MyMate):
    pass
 
 

自定义元类控制类的调用

控制类的调用过程 关键在于call函数, 类也是对象,调用类必然也会执行call函数
 
class MyMate(type):
    def __init__(self,name,bases,dic):
        print("run")
        if not dic.get("__doc__"):
            raise TypeError("类必须有文档注释!")
        if not name.istitle():
            raise TypeError("类名必须大写开头!")
        super().__init__(name,bases,dic)
    def __call__(self, *args, **kwargs):
        # 创建空对象
        # 调用init
        # 返回初始化后的对象
        obj = object.__new__(self)
        self.__init__(obj,*args,**kwargs)
        return obj
class Foo(object,metaclass=MyMate):
    """
    """
    def __init__(self):
        print("初始化对象")
    pass
f = Foo()
print(f)
 
 

元类实现单例

什么是单例,
单例是指的是单个实例,指一个类智能有一个实例对象
为什么要用单例
当一个类的实例中的数据不会变化时使用单例,数据是不变的
例如开发一个音乐播放器程序,音乐播放器可以封装为一个对象,那你考虑一下,当你切歌的时候,是重新创建一个播放器,还是使用已有的播放器?
因为播放器中的数据和业务逻辑都是相同的没有必要创建新的,所以最好使用单例模式,以节省资源,
 
#使用classmethod 实现单例
class Player():
    def __init__(self):
        print("创建播放器了")
    __play = None
    @classmethod
    def get_player(cls):
        if not cls.__play:
            cls.__play = Player()
        return cls.__play
p1 = Player.get_player();
p1 = Player.get_player();
p1 = Player.get_player();
p1 = Player.get_player();
 
该方法无法避免使用者直接调用类来实例化,这样就不是单例了
使用元类实现单例模式
 
#在类定义时 自动执行init 在init中创建实例 call中直接返回已有实例
class MyMeta(type):
    __instance = None
    def __init__(self,name,bases,dic):
        if not self.__instance:
            self.__instance = object.__new__(self)
            self.__init__(self.__instance)
        super().__init__(name, bases, dic)
    def __call__(cls):
        return cls.__instance
class Player(metaclass=MyMeta):
    def __init__(self):
        print("创建播放器了")
        
Player()
Player()
# 仅执行一次创建播放器

第四十九天 mysql 索引 元类的更多相关文章

  1. 孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数

    孤荷凌寒自学python第四十九天继续研究跨不同类型数据库的通用数据表操作函数 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 不同类型 ...

  2. mysql进阶(二十六)MySQL 索引类型(初学者必看)

    mysql进阶(二十六)MySQL 索引类型(初学者必看)   索引是快速搜索的关键.MySQL 索引的建立对于 MySQL 的高效运行是很重要的.下面介绍几种常见的 MySQL 索引类型.   在数 ...

  3. mysql系列十、mysql索引结构的实现B+树/B-树原理

    一.MySQL索引原理 1.索引背景 生活中随处可见索引的例子,如火车站的车次表.图书的目录等.它们的原理都是一样的,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的 ...

  4. C#高级编程四十九天----队列

    队列 1.Queue定义 System.Collections.Queue类表示对象的先进先出集合,存储在Queue(队列)中的对象在一端插入,从还有一端移除. 2.长处 (1).能对集合进行顺序处理 ...

  5. Python学习日记(四十二) Mysql数据库篇 十

    前言 当我们自己去写SQL代码的时候有时候会因为不熟练会导致效率低,再之后要进行许多的优化,并且操作也较为繁琐.因此ORM框架就能够解决上面的问题,它能根据自身的一些规则来帮助开发者去生成SQL代码. ...

  6. python第四十九天--paramiko模块安装大作战

    准备开始学习:paramiko模块,发现这个模块十分难搞 安装不上 搞了半天,win10 64下 pytyon 3.6 的 paramiko模块 死活安不上,在网上不断的找资料,可是没有用,没有用啊 ...

  7. 性能测试四十:Mysql存储过程造数据

    性能测试是基于大量数据的,而进行性能测试之前肯定没那么多数据,所以就要自己准备数据 数据构造方法: 1.业务接口 -- 适合数据表关系复杂 -- 优点:数据完整性比较好2.存储过程 -- 适合表数量少 ...

  8. shell学习四十九天----进程建立

    进程 前言:进程指的是运行中程序的一个实例.新进程由fork()与execve()等系统调用所起始,然后运行,知道他们下达exit()系统调用为止. linux系统都支持多进程.尽管计算机看起来像是一 ...

  9. python学习第四十九天XML模块的用法

    xml是实现不通语言或程序之间进行数据交换的协议,跟json差不多,但是json用起来简单,还没诞生json,以前都是用xml,下面讲述XML模块的用法. 1,导入xml模块 import xml 2 ...

随机推荐

  1. 【C#复习总结】探究各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字

    前言 先普及一下线程安全和类型安全 线程安全: 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的 ...

  2. PV、UV、IP、TPS、QPS、RPS、两天、吞吐量、 并发用户数 术语

    跟网站打交道,经常可以听到数据分析之类的专有名词,如pv多少.ip多少.tps多少之类的问题.下面就这些常见的数据给出其释义. PV   即 page view,页面浏览量         用户每一次 ...

  3. MySQL 数据库 初识

    ---------------------------------------------确定目标,认准目标,前进,克服困难,前进,克服困难,前进克服困难,前进. # # -------------- ...

  4. 出题人的女装(牛客练习赛38题B) (概率+分式运算)

    链接:https://ac.nowcoder.com/acm/contest/358/B来源:牛客网 出题人的女装 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...

  5. (FZU 2150) Fire Game (bfs)

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2150 Problem Description Fat brother and Maze are playing ...

  6. ElasticSearch 入门

    http://www.oschina.net/translate/elasticsearch-getting-started?cmp ElasticSearch 简单入门 返回原文英文原文:Getti ...

  7. python读取文件内的IP信息 练习

    代码如下: #导包 import fileinput import re def readArw(): for line in fileinput.input(r"G:/raw.txt&qu ...

  8. [转帖]linux下的X server:linux图形界面原理

    linux下的X server:linux图形界面原理 https://www.cnblogs.com/liangxiaofeng/p/5034912.html linux下的X server:lin ...

  9. CMake--静态库与动态库构建

    小结内容 建立一个静态库和动态库,提供 HelloFunc 函数供其他程序编程使用, HelloFunc 向终端输出Hello World 字符串. 安装头文件与共享库. 1.代码与CMakeList ...

  10. ORA-28000: the account is locked解决办法

    ORA-28000: the account is locked第一步:使用PL/SQL,登录名为system,数据库名称不变,选择类型的时候把Normal修改为Sysdba;第二步:选择myjob, ...