廖雪峰Python学习笔记——使用元类
元类(MetaClasses)
元类提供了一个改变Python类行为的有效方式。
元类的定义是“一个类的类”。任何实例是它自己的类都是元类。
class demo(object):
pass
obj = demo()
print "Class of obj is {0}".format(obj.__class__)
print "Class of obj is {0}".format(demo.__class__)
# Class of obj is <class '__main__.demo'>
# Class of obj is <type 'type'>
在上例中,我们定义了一个类demo,并且生成了一个该类的对象obj。首先,可以看到obj的__class__是demo。有意思的来了,那么demo的class又是什么呢?可以看到demo的__class__是type。
所以说type是python类的类,换句话说,上例中的obj是一个demo的对象,而demo本身又是type的一个对象。
所以说type就是一个元类,而且是python中最常见的元类,因为它使python中所有类的默认元类。
因为元类是类的类,所以它被用来创建类(正如类是被用来创建对象的一样)。但是,难道我们不是通过一个标准的类定义来创建类的么?的确是这样,但是python内部的运作机制如下:
- 当看见一个类定义,python会收集所有属性到一个字典中。
- 当类定义结束,python将决定类的元类,我们就称它为Meta吧。
- 最后,python执行Meta(name, bases, dct),其中:
a. Meta是元类,所以这个调用是实例化它。
b. name是新建类的类名。
c. bases是新建类的基类元组
d. dct将属性名映射到对象,列出所有的类属性。
那么如何确定一个类(A)的元类呢?简单来说,如果一个类(A)自身或其基类(Base_A)之一有__metaclass__属性存在,则这个类(A/Base_A)就是类(A)的元类。否则type就将是类(A)的元类。
metaclass 原理
metaclass的原理其实是这样的:当定义好类之后,创建类的时候其实是调用了type的__new__方法为这个类分配内存空间,创建
好了之后再调用type的__init__方法初始化(做一些赋值等)。所以metaclass的所有magic其实就在于这个__new__方法里面了。
说说这个方法:__new__(cls, name, bases, attrs)
cls: 将要创建的类,类似与self,但是self指向的是instance,而这里cls指向的是class
name: 类的名字,也就是我们通常用类名.__name__获取的。
bases: 基类
attrs: 属性的dict。dict的内容可以是变量(类属性),也可以是函数(类方法)。
所以在创建类的过程,我们可以在这个函数里面修改name,bases,attrs的值来自由的达到我们的功能。这里常用的配合方法是
getattr和setattr(just an advice)
廖雪峰Python学习笔记——使用元类的更多相关文章
- 廖雪峰Python学习笔记——类和实例
Class MyList(list): __metaclass__ = ListMetaclass #它表示在创建MyList这个类时,必须通过 ListMetaclass这个元类的LIstMetac ...
- 廖雪峰Python学习笔记——序列化
序列化 定义:程序运行时所有变量都存在内存中,把变量从内存中变成可存储或可传输的过程称为序列化pickling,在其他语言中称为serialization,marshalling,flattening ...
- python 学习笔记7(类/对象的属性;特性,__getattr__)
27. 属性的__dict__系统 1)对象的属性可能来自: 其类的定义,叫做类属性 继承父类的定义 该对象实例定义(初始化对象时赋值),叫做对象属性 2)对象的属性存储在对象的 __dict__ 属 ...
- Python学习笔记:05类
类 Python是面向对象的语言,面向对象最重要的三个优点有: 多态:多态使对象具备不同的行为方式.(可以认为声明了接口,但是实现方式可能多样) 封装:封装是对全局作用域中隐藏多余信息的原则(创建对象 ...
- Python学习笔记总结(三)类
一.类简单介绍 1.介绍 类是Python面向对象程序设计(OOP)的主要工具,类建立使用class语句,通过class定义的对象. 类和模块的差异,类是语句,模块是文件. 类和实例 实例:代表程序领 ...
- python学习笔记(六)、类
Python与java.c++等都被视为一种面向对象的语言.通过创建自定义类,用于处理各种业务逻辑.面向对象有封装.继承.多态三个特征,这也是面子对象语言的通用特征. 1 封装 封装,是值向外部隐藏内 ...
- python学习笔记9-单元测试unittest
Python中有一个自带的单元测试框架是unittest模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作. 在说unittest之前,先说几个概念: TestC ...
- Python学习笔记8-单元测试(1)
源代码: roman_mumeral_map = (('M',1000), ('CM',900), ('D',500), ('CD',400), ('C',100), ('XC',90), ('L', ...
- python学习笔记六--用户自定义类
一.类: 1. 面向对象. 2. 定义了新的对象类型. 定义了两个属性:name,pay 定义了两个方法:lastName,giveRaise
随机推荐
- 利用委托机制处理.NET中的异常
WinForm代码 private void button1_Click(object sender, EventArgs e) { try { Convert.ToInt32("abcd& ...
- 使用jsonp跨域发送请求
如果获取的数据文件存放在远程服务器上(域名不同,也就是跨域获取数据),则需要使用jsonp类型. 使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面. ...
- 『SpringMVC』<context:include-filter>&<context:exclude-filter>爬坑
原文地址:https://segmentfault.com/a/1190000012972619 大家好,我是猪弟,猪在我心中从来不是蠢的代名词,而是懒的代名词,本次准备记录一个在开发测试过程中遇到的 ...
- 白盒静态自动化测试工具:FindBugs使用指南
目 录 1 FINDBUGS介绍 2 在ECLIPSE中安装FINDBUGS插件 3 在ECLIPSE中使用FINDBUGS操作步骤 3.1 ...
- x-www-form-urlencoded
就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对,比如,name=java&age = 23 postman: 2.ajax传值
- gdb 调试带参数程序
在gdb中,运行程序使用r或是run命令. 程序的运行,你有可能需要设置下面四方面的事. 1.程序运行参数. set args 可指定运行时参数.(如:set args 10 20 30 40 50) ...
- 并发编程(五)LockSupport
并发编程(五)LockSupport LockSupport 提供 park() 和 unpark() 方法实现阻塞线程和解除线程阻塞,实现的阻塞和解除阻塞是基于"许可(permit)&qu ...
- OSGi 系列(十六)之 JDBC Service
OSGi 系列(十六)之 JDBC Service compendium 规范提供了 org.osgi.service.jdbc.DataSourceFactory 服务 1. 快速入门 1.1 环境 ...
- 强制另存文件和加扩展名的代码c#
强制另存为文件+扩展名的代码using System;using System.Collections.Generic;using System.Linq;using System.Web; name ...
- predict_proba 的使用