python3元类简介(metaclass)

在Python中可以用内置函数type查看对象的类型,isinstance查看某个对象是某个类实例,通过type可以实现动态类,以及通过metaclass实现动态类

type()与isinstance()判断对象类型

Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.In [1]: from selectors import SelectSelectorIn [2]: type(SelectSelector)
Out[2]: abc.ABCMetaIn [3]: from abc import ABCMetaIn [4]: type(ABCMeta)
Out[4]: typeIn [5]: ss = SelectSelector()In [6]: type(ss)
Out[6]: selectors.SelectSelectorIn [7]: from datetime import dateIn [8]: now = date.today()In [9]: type(now)
Out[9]: datetime.dateIn [10]: type(date)
Out[10]: typeIn [16]: isinstance(SelectSelector, ABCMeta)
Out[16]: TrueIn [17]: isinstance(ABCMeta, type)
Out[17]: TrueIn [18]: isinstance(ss, SelectSelector)
Out[18]: True
  • type(object) -> the object's type 获取对象的类型
  • isinstance(obj, class_or_tuple 判断对象是否是某一class的实例或者一组class其中一个的实例

通过上面的测试可以得出的结论

  • 类的实例的类型是类,如now是date类型

  • 一个类如果没有metaclass,则该类的类型是type,(默认的),如date类的类型是type

  • 一个类如果有metaclass(其基类有也可以),则该类的类型为其metaclass类,如SelectSelector类的类型为ABCMeta

  • date是type的实例,type是哪个?

  • metaclass是什么?为啥那么特殊?作用几个?

instance 				class				metaclassinstance of			instance of

type()实现动态类

type()另一个功能是动态的创建一个类型

>>> def fn(self, name='world'):
...     print('hello %s' % name)
...
>>> HH = type('Hello', (object,),dict(hello=fn))
>>> h = HH()
>>> h.hello()
hello world

type()的三个参数:
1)class的名称;
2)继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
3)class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

类是一个对象

  • type 可以创建类
  • type 创建的对象拥有创建对象的能力(也就是类)
  • type 就是 Python 中所有类的元类(metaclass)

metaclass

元类 并不是某一个类的名字,它是一个概念,是一种Python的思想。

python2中的用法

#!/usr/bin/env python2
# -*- coding: utf-8 -*-' Simple ORM using metaclass '__author__ = 'Michael Liao'class Field(object):def __init__(self, name, column_type):self.name = nameself.column_type = column_typedef __str__(self):return '<%s:%s>' % (self.__class__.__name__, self.name)class StringField(Field):def __init__(self, name):super(StringField, self).__init__(name, 'varchar(100)')class IntegerField(Field):def __init__(self, name):super(IntegerField, self).__init__(name, 'bigint')class ModelMetaclass(type):def __new__(cls, name, bases, attrs):if name=='Model':return type.__new__(cls, name, bases, attrs)print('Found model: %s' % name)mappings = dict()for k, v in attrs.iteritems():if isinstance(v, Field):print('Found mapping: %s ==> %s' % (k, v))mappings[k] = vfor k in mappings.iterkeys():attrs.pop(k)attrs['__mappings__'] = mappings # 保存属性和列的映射关系attrs['__table__'] = name # 假设表名和类名一致return type.__new__(cls, name, bases, attrs)class Model(dict):__metaclass__ = ModelMetaclassdef __init__(self, **kw):super(Model, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Model' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = valuedef save(self):fields = []params = []args = []for k, v in self.__mappings__.iteritems():fields.append(v.name)params.append('?')args.append(getattr(self, k, None))sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))print('SQL: %s' % sql)print('ARGS: %s' % str(args))# testing code:class User(Model):id = IntegerField('uid')name = StringField('username')email = StringField('email')password = StringField('password')u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()

python3中的应用

#!/usr/bin/env python3
# -*- coding: utf-8 -*-' Simple ORM using metaclass '__author__ = 'Michael Liao'class Field(object):def __init__(self, name, column_type):self.name = nameself.column_type = column_typedef __str__(self):return '<%s:%s>' % (self.__class__.__name__, self.name)class StringField(Field):def __init__(self, name):super(StringField, self).__init__(name, 'varchar(100)')class IntegerField(Field):def __init__(self, name):super(IntegerField, self).__init__(name, 'bigint')class ModelMetaclass(type):def __new__(cls, name, bases, attrs):if name=='Model':return type.__new__(cls, name, bases, attrs)print('Found model: %s' % name)mappings = dict()for k, v in attrs.items():if isinstance(v, Field):print('Found mapping: %s ==> %s' % (k, v))mappings[k] = vfor k in mappings.keys():attrs.pop(k)attrs['__mappings__'] = mappings # 保存属性和列的映射关系attrs['__table__'] = name # 假设表名和类名一致return type.__new__(cls, name, bases, attrs)class Model(dict, metaclass = ModelMetaclass):def __init__(self, **kw):super(Model, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Model' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = valuedef save(self):fields = []params = []args = []for k, v in self.__mappings__.items():fields.append(v.name)params.append('?')args.append(getattr(self, k, None))sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))print('SQL: %s' % sql)print('ARGS: %s' % str(args))# testing code:class User(Model):id = IntegerField('uid')name = StringField('username')email = StringField('email')password = StringField('password')u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()

参考

Python3 元类(metaclass)
Understanding Python metaclasses

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux ps 命令使用

Linux中的ps命令是Process Status的缩写。ps命令用来列出系统中当前运行的那些进程。ps命令列出的是当前那些进程的快照&#xff0c;就是执行ps命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用top命令。 linux上进程有5种状态 ps命令使…

UML序列图总结

序列图主要用于展示对象之间交互的顺序。 序列图将交互关系表示为一个二维图。纵向是时间轴&#xff0c;时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时&#xff0c;角色用一条虚线表示&#xff0c;当对象的过程处于激活…

UML用例图总结

用例图主要用来描述 用户、需求、系统功能单元 之间的关系。它展示了一个外部用户能够观察到的系统功能模型图。 【用途】&#xff1a;帮助开发团队以一种可视化的方式理解系统的功能需求。 用例图所包含的元素如下&#xff1a; 1. 参与者(Actor) 表示与您的应用程序或…

动态规划--换零钱

题目描述 想兑换100元钱&#xff0c;有1,2,5,10四种钱&#xff0c;问总共有多少兑换方法 递归解法 #include<iostream> using namespace std; const int N 100; int dimes[] {1, 2, 5, 10}; int arr[N1] {1}; int coinExchangeRecursion(int n, int m) //递归…

学生表 课程表 成绩表 教师表常用SQL语句

学生表 课程表 成绩表 教师表 50个常用sql语句 建表 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 ---- If database exists the same name datatable deletes it. IF EXISTS(SELECT TABLE_NAME FRO…

Linux网络编程常见面试题

概述 TCP和UDP是网络体系结构TCP/IP模型中传输层一层中的两个不同的通信协议。 TCP&#xff1a;传输控制协议&#xff0c;一种面向连接的协议&#xff0c;给用户进程提供可靠的全双工的字节流&#xff0c;TCP套接口是字节流套接口(stream socket)的一种。UDP&#xff1a;用户…

sizeof与offsetof有关的结构体详解

sizeof与offsetof在程序中经常遇到&#xff0c;但在面试中其应用使得许多小伙伴吃闭门羹&#xff0c;被面试官问得哑口无言。接下来对两者的应用做详细介绍。 关于sizeof 定义 sizeof乃C/C中的一个操作符(operator), 简单的说其作用就是返回一个对象或者类型所占的内存字节数…

linux线程间同步(1)读写锁

读写锁比mutex有更高的适用性&#xff0c;可以多个线程同时占用读模式的读写锁&#xff0c;但是只能一个线程占用写模式的读写锁。 1. 当读写锁是写加锁状态时&#xff0c;在这个锁被解锁之前&#xff0c;所有试图对这个锁加锁的线程都会被阻塞&#xff1b; 2. 当读写锁在读加…

linux线程间同步(1)互斥锁与条件变量

线程的最大特点是资源的共享性&#xff0c;但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步&#xff0c;最常用的是互斥锁、条件变量和信号量以及读写锁。 互斥锁(mutex) 互斥锁&#xff0c;是一种信号量&#xff0c;常用来防止两个进程或线…

Linux下压缩包生成与解压命令以及进度

不同后缀压缩包的打包与加压命令 .tar 解包&#xff1a;tar xvf FileName.tar打包&#xff1a;tar cvf FileName.tar DirName .gz 解压1&#xff1a;gunzip FileName.gz解压2&#xff1a;gzip -d FileName.gz压缩&#xff1a;gzip FileName .tar.gz 和 .tgz 解压&#xff1a;…

经典面试题

谷歌面试题&#xff1a;1024! 末尾有多少个0&#xff1f; 末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数&#xff0c;所以我们只需统计因子5的个数。 是5的倍数的数有&#xff1a; 1024 / 5 204个;对于25,50这些数据统计一次,但实际的是包含两个…

共享内存:mmap函数实现

内存映射的应用: 以页面为单位,将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能;将特殊文件进行匿名内存映射&#xff0c;可以为关联进程提供共享内存空间;为无关联的进程提供共享内存空间&#xff0c;一般也是将…

MSYS2开发环境搭建

MSYS2开发环境搭建 软件安装 下载msys2-x86_64软件包 https://www.msys2.org/&#xff0c;双击安装到某根目录下&#xff0c;比如D:\msys64。 pacman是MSYS2自带的软件管理工具&#xff1a; 可通过修改msys64\etc\pacman.d下的三个文件修改软件源&#xff0c;可供选择的源有…

设置python路径

在python开发应用&#xff0c;我们多数是通过pip、easy_install等工具将需要的python安装到自己机子上就可以应用了&#xff0c;但是我们完成开发给用户使用时&#xff0c;程序运行环境就是一个问题。当然&#xff0c;你可以要求客户按照你的方法安装依赖的库&#xff0c;这种方…

linux动态库查找路径以及依赖关系梳理

编译时与运行时库的路径 linux下&#xff0c;编译时与运行时库的搜索路径是不同的 运行时动态库的路径搜索顺序 LD_PRELOAD环境变量&#xff0c;一般用于hack 编译目标代码时指定的动态库搜索路径(指的是用 -wl,rpath 或-R选项而不是-L)&#xff0c;readelf -d命令可以查看编…

eclipse--android开发环境搭建教程

引言 在windows安装Android的开发环境不简单也说不上算复杂&#xff0c;但由于国内无法正常访问google给android开发环境搭建带来不小的麻烦。现将本人搭建过程记录如下&#xff0c;希望会对投身android开发的小伙伴有所帮助。 android开发环境部署过程 安装JDK环境 下载安装…

pip工具使用总结以及常用库PIL、freetype的安装

pip工具安装使用 pip为python库软件管理工具pip docs 安装 wget https://bootstrap.pypa.io/ez_setup.py -O - | python 安装setuptools https://pypi.python.org/pypi/setuptoolswget https://bootstrap.pypa.io/get-pip.py -O - | python 安装pip工具 ttps://pypi.python.…

【技巧】Chrome应用技巧

把Chrome浏览器变成文本编辑器 在浏览器地址栏中输入一行代码&#xff1a;data:text/html, <html contenteditable>&#xff0c;回车即可把浏览器变临时编辑器。【CtrlShiftJ】调出JavaScript控制台&#xff0c;在控制台输入&#xff1a; document.body.contentEditable…

eclipse--python开发环境搭建

pydev插件介绍 PyDev is a Python IDE for Eclipse pydev官方网站&#xff1a;http://www.pydev.org/ 在Eclipse中安装pydev插件 启动Eclipse, 点击Help->Install New Software… 在弹出的对话框中&#xff0c;点Add 按钮。 Name中填:Pydev, Location中填http://pydev.or…

Win7虚拟无线AP以及Android手机抓包

设备要求 Windows7操作系统装有无线网卡的笔记本或台式机无线网卡必须支持“承载网络” 查看无线网卡是否支持“承载” 方法一: 开始菜单→所有程序→附件→命令提示符→右键“以管理员权限运行”; 键入命令“netsh wlan show drivers”,查看“支持承载网络”这一项,如果是…