元类介绍

一切源自于一句话: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. Windows Community Toolkit 4.0 - DataGrid - Overview

    概述 Windows Community Toolkit 4.0 于 2018 月 8 月初发布:Windows Community Toolkit 4.0 Release Note. 4.0 版本相 ...

  2. 学习用Node.js和Elasticsearch构建搜索引擎(1):了解并运行Elasticsearch

    1.学习Elasticsearch概述. 了解Elasticsearch是什么?能做什么?可以查一下elasticsearch.lucene等的相关介绍,另外也可以查查资料比较一下其它的搜索引擎sph ...

  3. Mysql多实例之mysql服务脚本

    1. #init port=3306 mysql_user="root" mysql_pwd="cancer" CmdPath="/applicati ...

  4. H5 55-行高

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Tarjan算法(缩点)

    因为最近在学2sat,需要学习前置技能—Tarjan算法,所以花了一天的时间学习这个算法 算法步骤: 1.从一个点开始dfs,并加入栈 2.如果下一个点没有到过,跳到第一步 3.如果下一个点到过,并且 ...

  6. 软工网络15团队作业4——Alpha阶段敏捷冲刺

    Deadline: 2018-4-29 10:00PM,以提交至班级博客时间为准. 根据以下要求,团队在日期区间[4.16,4.29]内,任选8天进行冲刺,冲刺当天晚10点前发布一篇随笔,共八篇. 另 ...

  7. Python之发邮件

    使用模块yagmail(使用收藏的yagmail,现在的第三方模块不能解决中文乱码问题) import yagmail user='xxx@126.com' password='xxxxxx' #使用 ...

  8. Python3练习题 022:用递归函数反转字符串

    方法一 str = input('请输入若干字符:')   def f(x):     if x == -1:         return ''     else:         return s ...

  9. 【Python3练习题 013】 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字

    a=input('输入数字>>>') count=int(input('几个数字相加>>>')) ret=[] for i in range(1,count+1): ...

  10. Azure系列2.1 —— com.microsoft.azure.storage.blob

    网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习心得做下笔记,文中不正确地方请大家指正. Azure Blob ...