zoukankan      html  css  js  c++  java
  • Python学习笔记八 面向对象高级编程(二)元类

    参考教程:廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

    在廖老师的学习网站里“使用元类”这部分还是把我给看晕了...网上搜到一篇感觉讲的相对易懂一些,贴出链接:两句话掌握 Python 最难知识点——元类——以此文作为这篇笔记的源本。

    “道生一,一生二,二生三,三生万物”

    1、在Python世界中,“type”即为道,即是生出各种类、对象、变量等等一切的源头。

    2、一——即是metaclass(元类,也叫类生成器)

    3、二——即是各种常规的类(class)

    4、三——即是实例(instance)

    5、万物——即是实例的各种属性和方法

    #创建一个Student类,这个类即为“二”
    class Student():
    def printinfo(self):
            print("It is a instance of Student!")
            
    #创建Student的实例s,即为“二生三”
    s=Student()
    
    #使用实例的属性、方法,即为“三生万物”
    s.printinfo()

    这段代码提现从二到万物的过程,那么对于Student类这个“二”从何而来呢?

    我们看到的定义类的class Student()...这些代码,实际上如下:

    def fn(self):
        print("It is a instance of Student!")
    Student=type('Student',(object,),dict(printinfo=fn))

    注意到这里,Student类是通过type()方法生成的,其中有三个参数,分别为设置类的名字,使用一个元组明确该类的父类,使用一个字典给出这个类的方法。

    type是“道”,可以先通过type生成元类,再由元类生成各种类。

    “元类”

    一般来说,元类都被命名为后缀Metaclass。

    先看一个定义元类的例子:假设需要一个可以自动打招呼的元类,它里面的类方法有时需要say_Hello,有时需要say_Hi,有时又需要say_Sayolala,有时需要say_Nihao。

    class SayMetaclass(type):  #注意到元类均继承自type
        def __new__(cls,name,bases,attrs):
            attrs['say_'+name]=lambda self,value,saying=name:print(saying+','+value+'!')
            return type.__new__(cls,name,bases,attrs)

    注意:

    1、元类都是由"type"衍生出来的,所以父类必须传入type。

    2、元类的操作都是通过__new__()完成,第一个参数是将创建的类的对象(是否基本类似于self?),后面三个参数分别为:类名、父类、属性/方法。

    具体看这个代码:

    attrs['say_'+name]=lambda self,value,saying=name:print(saying+','+value+'!')

    这里是给每个类定义一个”'say_'+类名”的属性,具体在这里是一个方法,通过lambda定义的方法,这个方法有三个参数,第一个self,是因为是类的方法,所以必须第一个为self,第二个是常规的位置参数value,需要使用者自己传入,第三个是一个默认参数,默认为类名。

    通过这个元类继续生出各个类:

    class SayMetaclass(type):  #注意到元类均继承自type
        def __new__(cls,name,bases,attrs):
            attrs['say_'+name]=lambda self,value,saying=name:print(saying+','+value+'!')
            return type.__new__(cls,name,bases,attrs)
    
    #通过SayMetaclass创建一个Hello类
    #注意用法,参数除了第一个父类外,必须使用metaclass=标明该类使用的元类
    #因为这里类名是Hello
    #所以这个Hello类拥有一个“say_Hello”的属性
    #而这个属性又是一个方法,即等效于下面代码的方法:
    '''
    def say_Hello(self,value,saying='Hello'):
            print(saying+','+value+'!')
    '''
    class Hello(object,metaclass=SayMetaclass):
        pass
    Hello().say_Hello('World')  
    
    #基于元类继续创建新的类
    class Nihao(object,metaclass=SayMetaclass):
        pass
    Nihao().say_Nihao('China')  
    Nihao().say_Nihao('China',saying='Very Great') 
    
    #基于元类继续创建新的类
    class Sayolala(object,metaclass=SayMetaclass):
        pass
    Sayolala().say_Sayolala('Japan')  

    输出如下:

    Hello,World!
    Nihao,China!
    Very Great,China!
    Sayolala,Japan!
  • 相关阅读:
    StackExchange.Redis 文档翻译
    性能分析
    脚本
    KEYS,SCAN,FLUSHDB 等等,这些命令在哪里?
    事件
    发布/订阅 消息顺序
    Redis中的事务
    键、值以及通道
    管道和多路复用器
    配置
  • 原文地址:https://www.cnblogs.com/tsembrace/p/8684545.html
Copyright © 2011-2022 走看看