元类介绍

一切源自于一句话: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. 多模块后带来的问题解决方法 - OSGI原形(.NET)

    目前只做了基础的功能,比如: 各个模块单独的AppDomain容器 Activator激活 导出的服务检查 不过,虽说这样,但目前的这个版本已经能实现模块分离.互相依赖调用等功能了,对模块划分已经有很 ...

  2. Win10 Anaconda下TensorFlow-GPU环境搭建详细教程(包含CUDA+cuDNN安装过程)

    目录 前言 第一步:安装Anaconda 1.下载和安装 2.配置Anaconda环境变量 第二步:安装TensorFlow-GPU 1.创建conda环境 2.激活环境 3.安装tensorflow ...

  3. 我去年码了个表(WPF MvvM)

    又快个把月没写博客了(最近忙着学JAVA去了,都是被逼的/(ㄒoㄒ)/~~),然后用WPF码了个表,其实想加上那种提醒功能什么的,额,就这样了吧,主要是感受一下数据驱动的思想. 效果如下: 前端XAM ...

  4. matplot绘图基本使用

    先看一个最简单的例子 import matplotlib.pyplot as plt plt.figure() plt.subplot(211) plt.plot([1,2,3], color=''r ...

  5. github/gitlab同时管理多个ssh key

    之前一直用github,但是github有一个不好的地方,要是创建私有的项目的话需要付费,而gitlab上则可以免费创建管理私有的项目.由于最近想把自己论文的一些东西整理一下,很多东西还是不方便公开, ...

  6. Leetcode -- 394. Decode String

    Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...

  7. 全局关键字搜索:Element UI Table内容过滤\jQuery过滤器fastLiveFilter插件\BootstrapVue插件;

    ```html data:{ resultMaster: [], otableData:[], schfilter:'' } watch: { schfilter: function(val, old ...

  8. pdf转eps后存在大片空白的处理

    之前pdf转eps的方式是用acrobat直接转,发现每次转完后,图片都显示在一张A4纸上,插入到论文中时会出现大片空白:但在pdf中是没有这么多空白的,与裁剪没关系. 后来在 http://tex. ...

  9. java 工具

    JClassLib 4.2 发布了,该版本支持 Java 7 和 Java 8 的类文件属性查看. JClassLib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Cla ...

  10. C#设计模式之3:观察者模式

    C#中已经实现了观察者模式,那就是事件,事件封装了委托,使得委托的封装性更好,在类的内部定义事件,然后在客户端对事件进行注册: public class Subject { public event ...