设为首页 加入收藏

TOP

初识python元类(metaclass)(一)
2018-10-19 16:55:33 】 浏览:81
Tags:初识 python元类 metaclass

听过一句话,在python中一切皆对象,而在python3中统一了类和类型。

我们可以用type方法查看一个变量(对象)的类型,即是查看对象的类:

x=2
y='dasd'
z=[]
class Student:
    school='jjjj'
    def __init__(self,name):
        self.name=name


print(type(x),type(y),type(z),type(Student),)

#结果:<class 'int'> <class 'str'> <class 'list'> <class 'type'>
当然在了解元类之前,我们需要了解一些姿势点,方便以后运用。
1:python内置函数exec(解释:独立(在其他语言中不一定独立)执行一段python字符串代码,并留下一些东东)
exec(a,b,c) 我们一般是这样用。
  a:要执行的字符串代码
  b:a中可能用到的外部变量(字典格式,一般是全局的)
  c:返回执行a后产生的名称空间(不要问我是什么,字典格式)

name='wx'
a='''
k=name
j='das'
def pp():
    pass
'''
b={'name':name}
c={}
exec(a,b,c)
print(c)
#结果:{'k': 'wx', 'j': 'das', 'pp': <function pp at 0x0569A228>}
2.__call__方法(类中定义这方法时,实例化出的对象被调用时会触发此方法)
class Teacher:
    def __call__(self, *args, **kwargs):
        print('__call__ 执行')
        print(args)
        return 444

obj=Teacher()#实例化
print(obj('llll'))#调用对象,当然也可传参

'''结果:
__call__ 执行
('llll',)
444
'''
3.__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple,可变的也行)
提供给你一个自定义这些类的实例化过程的途径,还有就是实现自定义的metaclass。还有许多用途。
这里我们主要是用其创建一个新的对象.
class UpperStr(str):
    def __new__(cls, s):
        return super().__new__(cls,s.upper())

print(UpperStr('asdasd'))
#结果:ASDASD
class MyNew:
    def __init__(self,name,age):
        self.name=name
    def __new__(cls, *args, **kwargs):
       obj=super().__new__(cls)#造一个空对象,也调用了MyNew的__init__方法
       # #为对象加个属性
       obj.new_age=kwargs.get('age')
       return obj

obj=MyNew(name='da',age=18)
print(obj,vars(obj),)
#结果:<__main__.MyNew object at 0x057D4070> {'new_age': 18, 'name': 'da'}

'''
回到正题,我们查看类type(Student)时看到的Student类的类为type,也就是说Student类是由type类产生的,
我们把产生类的类称为元类,python中默认的元类是type
当我我们定义类的时候
'''
class Student(object,metaclass=type):
    #其实这里指定了类由哪个元类产生,默认是type
    #即是Student=type(.....) 由type类实例化而来
    pass
 
  

 

 

'''
那我们为毛要学习元类:为了掌握一种定义类的方式,在定义类时加一下限定条件。 我们定义类时,一种方式是用关键字class 这里我们来模拟一下class创建类的过程, 首先创建类需要什么? 1:类名 2:基类(父类) 3:类体代码(一堆字符串) ''' #类名 class_name='Student' #类的父类 class_bases=(object,) #类体 class_body=""" school='dh' def __init__(self,name,age): self.name=name self.age=age def study(self): print('%s is studying' %self.name) """ #类体定义的名字都会存放于类的名称空间中,与exec相似 class_dic={} exec(class_body,{},class_dic) print(class_dic) #结果{'school': 'dh', '__init__': <function __init__ at 0x04AEA2B8>, 'study': <function study at 0x04AEA270>}

 

那么调用元类type(也可以自定义)来产生类Student
'''
那么调用元类type(也可以自定义)来产生类Student
'''
Student=type(class_name,class_bases,class_dic)
print(Student,type(Student),isinstance(Student,type),Student.school)
#结果:<class '__main__.Student'> <class 'type'> True dh

通过上面产生的类过程,我们就可以自定义一个元类,即是写一个类,继承type,复写它的一些方法,如下:

class Mymeta(type):  # 继承默认元类的一堆属性
    def __init__(self, class_name, class_bases, class_dic):
        if not class_name.istitle():
            raise TypeError('类名首字母必须大写')

        super(Mymeta, self).__init__(class_name, class_bases, class_dic)
class student(object,metaclass=Mymeta):
    school = 'dh'
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def study(self):
        print('%s is studying' % self.name)

#则在定义阶段 会报错:TypeError: 类名首字母必须大写

这样就自定义了一个元类,并控制产生类的条件是类名必须是title。

当然,我们自定义的元类必须继承type,是为了继承默认元类的一堆属性。

其调用过程如下:

class Mymeta(type):  # 继承默认元类的一堆属性
    def __init__(sel
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇7月5号第二次直播学习笔记 下一篇在python3下使用OpenCV做离散余弦..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目