Python 面向对象高阶-----metaclass
Python 面向对象高阶-----metaclass
前言
类也是对象,既然类是对象,那就自然是某个东西的实例化,这个东西就是type
首先看下type是怎么回事
type
type最常用的方法就是查看类型,这只是他的基础用法罢了
>>> print(type(1))
<type 'int'>
>>> print(type(""))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>
type 通过传入其他参数也可以实现类的创建
普通方式创建类:
class Foo(object):
bar = True def echo_bar(self):
print(self.bar)
继承关系的方式
class FooChild(Foo):
pass
type 方式创建类:
def echo_bar(self):
print(self.bar) Foo = type('Foo', (), {'bar':True, 'echo_bar': echo_bar})
有继承关系方式:
FooChild = type('FooChild', (Foo, ), {})
以上两种方法是等效的
type 的类创建方式的参数需要三个:
- 类的名字
- 一组"类的父类"的元组(tuple) (这个会实现继承,也可以为空)
- 字典 (类的属性名与值,key-value的形式,不传相当于为空,如一般写法中的pass).
metaclass
说白了,函数 type 就是一个特殊的metaclass.
python在背后使用 type 创造了所有的类。type是所有类的metaclass.
在python中,一切皆为对象:整数、字符串、函数、类.所有这些对象,都是通过类来创造的.
>>> age = 35
>>> age.__class__
<type 'int'> >>> name = 'bob'
>>> name.__class__
<type 'str'> >>> def foo(): pass
>>> foo.__class__
<type 'function'> >>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>
而__class__的__class__则就是由 type 来的了
>>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>
metaclass就是创造类对象的工具.如果你喜欢,你也可以称之为"类的工厂".
type是python內置的metaclass。不过,你也可以编写自己的metaclass.
指定 metaclass
class Foo(metaclass=MyType): # python 3
# __metaclass__ = MyType # python 2
pass
流程
Foo中有__metaclass__这个属性吗?
有:
如果有,会在内存中通过__metaclass__创建一个名字为Foo的类对象。
没有:
如果没有__metaclass__,它会继续在Bar(父类)中寻找,并尝试做和前面同样的操作。
如果父类也没有找到__metaclass__,它就会在模块(module)中去寻找__metaclass__,并尝试做同样的操作。
如果始终都找不到__metaclass__, 最终只能使用内置的type(这也是一个metaclass)来创建这个类对象。
自定义metaclass
使用metaclass的主要目的,是为了能够在创建类的时候,自动地修改类
自定义 metaclass 首先就需要自定义一个不同于 type 的自定义 MyType,能够实现之前的 type 的类创建功能基础上在实现其他想要的功能
class MyType(type):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs) def __call__(cls, *args, **kwargs):
obj = cls.__new__(cls) cls.__init__(obj,*args, **kwargs) return obj
在创建类的时候指定 metaclass 为 自定义的 MyType 即可
class Foo(object,metaclass=MyType): # metaclass 指定由谁来创建这个类
a1 = 123
def __init__(self):
pass def __new__(cls, *args, **kwargs):
return object.__new__(cls) def func(self):
return 666
那么在此类创建实例的时候的流程是怎样的呢?
foo = Foo()
流程

创建类时
先执行 MyType 的 __init__ 方法 ,由super 转向先执行 父类 type 的 __init__ 来创建类
类实例化时
当一个类在实例化时候,先执行 type 的 __call__ 方法 , __call__ 方法 的返回值就是实例化对象
__call__ 内部调用:
类.__new__ 方法 :创建对象
类.__init__ 方法 :对象初始化
Python 面向对象高阶-----metaclass的更多相关文章
- day37-1 面向对象高阶
目录 面向对象高阶 isinstance issubclass 反射(自省) 模块的使用 放在类的使用 call 面向对象高阶 isinstance 判断是否为实例化对象,以后可以用来取代type 和 ...
- python基础——高阶函数
python基础——高阶函数 高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数a ...
- Python的高阶函数小结
一. 高阶函数定义 简而言之,Python的高阶函数就是指一个函数作为参数传递给另外一个函数的用法. 举一个最简单的高阶函数来说明: >>> def add(x,y,f): retu ...
- python 验证码 高阶验证
python 验证码 高阶验证 标签: 验证码python 2016-08-19 15:07 1267人阅读 评论(1) 收藏 举报 分类: 其他(33) 目录(?)[+] 字符型图片验证 ...
- python之高阶函数编程
在这篇文章中我指出两点: 第一:系统函数可以被覆盖 比如: a=abs(-10) print a 10 但是,如果把函数本身赋值给变量呢? f = abs f <built-in functio ...
- Python笔记-高阶函数
1.函数式编程 函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数! 传入函数 既然 ...
- python的高阶函数式编程
首先 函数式编程≠函数编程,就跟计算机≠计算,因为计算机基于硬件,计算基于算法,所以函数式编程是倾向于算法. 高阶函数定义: 一个函数接受的这个参数,而这个参数也是一个函数,称之为高阶函数 例如: ...
- Python练习-高阶函数-2018.12.03
1.函数式编程的概念 在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言. 而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远 ...
- Python 基础 高阶函数
python 把函数作为参数 如果传入abs 作为参数 def add(x,y,y): return f(x) + f(y) add(-5,9,abs) 根据函数的定义,函数执行的代码实际上是. ab ...
随机推荐
- Get-CrmSetting返回Unable to connect to the remote server的解决办法
摘要: 微软动态CRM专家罗勇 ,回复302或者20190125可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 在Dynam ...
- 关于Windows系统不会变慢的设想
记录软件安装的过程,比如创建了哪些服务,哪些计划任务以及启动项等等. 然后软件安装完成后把关于软件的进程,服务,计划任务等都删掉. 然后手动创建一个脚本,用脚本代替软件的启动.比如,如果要启动sqls ...
- Django数据库--事务及事务回滚
数据库的读写操作中,事务在保证数据的安全性和一致性方面起着关键的作用,而回滚正是这里面的核心操作.Django的ORM在事务方面也提供了不少的API.有事务出错的整体回滚操作,也有基于保存点的部分回滚 ...
- 为archlinux选择国内镜像
pacman-mirrors --country China && pacman -Syyu
- windows下php7.1安装redis扩展以及redis测试使用全过程
最近做项目,需要用到redis相关知识.在Linux下,redis扩展安装起来很容易,但windows下还是会出问题的.因此,特此记下自己实践安装的整个过程,以方便后来人. 一,php中redis扩展 ...
- Thinkphp volist 多重循环原样输出数组key值的使用总结
最近因为项目的缘故,要使用到volist.在这个过程中,遇到了一些小问题,主要就是volist在循环输出多重数据的时候,如何输出key.网上查阅了不少资料,很失望的是,大多资料就是粘贴复制Thinkp ...
- 让 Windows7 - 64bit 支持 VC++ 6.0 的解决方法(无法启动此程序,因为计算机中丢失 MSVCRTD.dll。尝试重新安装该程序以解决此问题)
源地址:https://www.cnblogs.com/poissonnotes/p/4372136.html 无法启动此程序,因为计算机中丢失 MSVCRTD.dll.尝试重新安装该程序以解决此问题 ...
- LeetCode算法题-Binary Number with Alternating Bits(Java实现)
这是悦乐书的第292次更新,第310篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第160题(顺位题号是693).给定正整数,检查它是否具有交替位:即它的二进制数的任意两 ...
- 使用github 的相关博客
基于hexo+github搭建一个独立博客 如何用Github的gh-pages分支展示自己的项目 使用git clone error: RPC failed Git的使用-- ...
- python print 在windows上 出现 Bad file descriptor error
先说一下情况,一个python写的采集程序,做成windows服务在windows上运行. 这个问题出现的挺奇特,本来一套采集程序,一个采集文件的时候没问题,两个采集文件的时候也没问题,当三个采集文件 ...