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!

 

posted @ 2018-03-31 22:29  tsembrace  阅读(219)  评论(0编辑  收藏  举报