一、什么是元类

二、如何使用元类

(一)不依赖class关键字创建一个自定义类

(二)自定义元类控制类的产生

(三)自定义元类控制类的调用

一、什么是元类

在python中,一切皆对象,而对象都是由类实例化得到的。所以类也是对象,而类的类就是元类,其实 type 就是元类。

二、如何使用元类

class Teacher:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name) tea1=Teacher('egon',18,'male')
print(type(tea1)) #<class '__main__.Teacher'>
print(type(Teacher)) #<class 'type'>
print(Teacher) #<class '__main__.Teacher'> 对象tea1是调用Teacher类得到的,如果说一切皆对象,那么Teacher也是一个对象,
只要是对象,都是调用一个类实例化得到的,即Teacher=元类(...),内置的元类是type

类与元类的关系:

  1. 调用元类---->自定义的类
  2. 调用自定义的类---->自定义的对象

class关键字创建自定义类的底层的工作原理,分为四步

  1. 先拿到类名:'Teacher'
  2. 再拿到类的基类们:(object,)
  3. 然后拿到类的名称空间(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,)
  4. 调用元类实例化得到自定义的类: Teacher=type('Teacher',(object,),{...})

自定义类的三个关键组成部分:

  1. 类名
  2. 类的基类们
  3. 类的名称空间

1、不依赖class关键字创建一个自定义类

创建之前需要了解一下exec函数

exec: 是一个python内置函数,可以将字符串的代码添加到局部名称空间中;

exec(字符串形式的代码, 全局名称空间, 局部名称空间)

#1. 拿到类名
class_name='Teacher'
#2. 拿到类的基类们:(object,)
class_bases=(object,)
#3. 拿到类的名称空间
class_dic={}
class_body="""
school = 'Qinghua' def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex def score(self):
print('%s is scoring' %self.name)
"""
exec(class_body,{},class_dic)
print(class_dic) #4.调用type得到自定义的类
Teacher=type(class_name,class_bases,class_dic)
print(Teacher) #<class '__main__.Teacher'> 跟用class定义的类一样 print(Teacher)
# print(Teacher.school)
# print(Teacher.score) tea1=Teacher('egon',18,'male')
print(tea1.__dict__)

2、自定义元类控制类的产生

模板:

#但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
class Mymeta(type):
def __init__(self,class_name,class_bases,class_dic):
print(self) #self--->Teacher
print(class_name)
print(class_bases)
print(class_dic) #Teacher=Mymeta('Teacher',(object,),{...})
class Teacher(object,metaclass=Mymeta): #metaclas--->元类
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name)

控类的产生:

1.控制类名必须用驼峰体:
2.类体必须有文档注释
class Mymeta(type):
school = 'Qinghua'
def __init__(self,class_name,class_bases,class_dic):
if class_name.islower():
raise TypeError('类名必须使用驼峰体') doc = class_dic.get('__doc__') if doc is None:
raise TypeError('类体中必须有文档注释') #Teacher=Mymeta('Teacher',(object,),{...})
class Teacher(object,metaclass=Mymeta): #metaclas--->元类
school = 'Qinghua'
def __init__(self,name,age,sex): #self--->Teacher
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name) print(Teacher.__dict__)

3、自定义元类控制类的调用

'''
class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
pass class Teacher(object): #Teacher=Mymeta('Teacher',(object,),{...})
school = 'Qinghua' def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex def score(self):
print('%s is scoring' %self.name) def __call__(self, *args, **kwargs):
print(self)
print(args)
print(kwargs)
tea1=Teacher('egon',18,'male') tea1(1,2,a=1,b=2) #__call__(tea1,(1,2).{'a':1,'b':2})
''' 总结:对象之所以可以调用,是因为对象的类中有一个函数__call__ 推导:如果一切皆对象,那么Teacher也是一个对象,该对象之所可以调用,肯定是这个对象的类中也定义了一个函数__call__ class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
def __call__(self, *args, **kwargs): #self=Teacher这个类,args=('egon',18,'male'),kwargs={}
# 1. 先产生一个空对象
tea_obj=self.__new__(self) #tea_obj是Teacher这个类的对象 self--->Teacher
# 2. 执行__init__方法,完成对象的初始属性操作
self.__init__(tea_obj,*args,**kwargs)
# 3. 返回初始化好的那个对象
return tea_obj class Teacher(object,metaclass=Mymeta): #Teacher=Mymeta('Teacher',(object,),{...})
school = 'Qinghua' #tea_obj,'egon',18,'male'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex def score(self):
print('%s is scoring' %self.name) tea1=Teacher('egon',18,'male') # 会触发Teacher的类(即元类)中的__call__函数
print(tea1)
print(tea1.__dict__)

Python 元类的基本介绍及使用的更多相关文章

  1. Python进阶丨如何创建你的第一个Python元类?

    摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...

  2. python元类:type和metaclass

    python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...

  3. Python 元类 - Metaclasses

    Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...

  4. Python元类实践--自己定义一个和collections中一样的namedtuple

    大家可能很熟悉在collections模块中有一个很好用的扩展数据类型-namedtuple. 如果你还不知道这个类型,那么请翻看标准手册. 我利用元类轻松定义一个namedtuple. 先把代码贴上 ...

  5. python元类理解2

    恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...

  6. 3.python元类编程

     1.1.propety动态属性 在面向对象编程中,我们一般把名词性的东西映射成属性,动词性的东西映射成方法.在python中他们对应的分别是属性self.xxx和类方法.但有时我们需要的属性需要根据 ...

  7. python 元类的简单解释

    本文转自博客:http://www.cnblogs.com/piperck/p/5840443.html 作者:piperck python 类和元类(metaclass)的理解和简单运用 (一) p ...

  8. Python元类(metaclass)以及元类实现单例模式

    这里将一篇写的非常好的文章基本照搬过来吧,这是一篇在Stack overflow上很热的帖子,我看http://blog.jobbole.com/21351/这篇博客对其进行了翻译. 一.理解类也是对 ...

  9. python元类深入解析

    元类 什么是元类 元类是类的类,是类的模板(就如对象的模板是类一样) 元类的实例为类,类的实例为对象 元类是用来产生类的 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,是运行时动 ...

随机推荐

  1. 14.libgdx的一些坑记录(持续更新)

    1. internal的文件路径 无法用list获取目录下文件     2.动态打包散图无法放入资源管理器,只能在资源加载器打包后的散图再合成打包,但都不如提前打包 3.资源加载器读入以texture ...

  2. BUAA 623 Chem is Try!

    http://oj55.bianchengla.com/problem/623/ 好久没写过题解了,昨天做了一道挺恶心的题目,贴一下代码上来.看了一下提交状况,好像我的代码挺短的了,至少我找不到比我短 ...

  3. JVM 调优 —— GC 长时间停顿问题及解决方法

    零. 简介 垃圾收集器长时间停顿,表现在 Web 页面上可能是页面响应码 500 之类的服务器错误问题,如果是个支付过程可能会导致支付失败,将造成公司的直接经济损失,程序员要尽量避免或者说减少此类情况 ...

  4. oracle 识别’低效执行’的SQL语句

    用下列SQL工具找出低效SQL: SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_ ...

  5. 微信接口开发报错invalid credential, access_token is invalid or not latest hint

    微信接口凭证access_token一定要全局管理 我们的查酒后台集成了微信公众平台的客服API接口,不用登录微信公众号的后台就可以直接给用户发送消息.最近,运营的同事反馈,通过微信查酒,后台无法直接 ...

  6. ubuntu14.04本地域名服务器配置

    dnsmasq 1 修改dnsmasq配置文件/etc/dnsmasq.conf # Change this line if you want dns to get its upstream serv ...

  7. ubuntu netstat 查看端口占用情况

    netstat 用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships ...

  8. 全面理解Python中的类型提示(Type Hints)

    众所周知,Python 是动态类型语言,运行时不需要指定变量类型.这一点是不会改变的,但是2015年9月创始人 Guido van Rossum 在 Python 3.5 引入了一个类型系统,允许开发 ...

  9. SuperSocket命令加载器 (Command Loader)

    在某些情况下,你可能希望通过直接的方式来加载命令,而不是通过自动的反射. 如果是这样,你可以实现你自己的命令加载器 (Command Loader): public interface IComman ...

  10. html手机端全屏显示和溢出问题

    <meta name="viewport" content="width=1200, initial-scale=0.3"> initial-sca ...