python类的应用_Python · 元类(Meta Class)及其应用
(这里是本章用到的 GitHub 地址)万物皆对象 —— Python
本章所介绍的元类(Meta Class)和之前介绍过的装饰器(Decorator)都是上面这句话的具现,其中装饰器告诉过我们“函数亦对象”,元类则会告诉我们“类亦对象”
Meta Class 是传说中的黑魔法、黑魔法中的战斗机(……)。我其实对它也只一知半解,所以以下说的内容可能仅展现了它神奇功用的冰山一角。不过作为一个入门教程来说的话、可能会刚刚好也说不定(其实只是在为自己的弱小找借口)(喂)
所谓的“类亦对象”和“函数亦对象”的思想类似:它意味着类可以被赋值给变量、通过变量也能创建该类的实例。举个栗子:
class Class:
def __init__(self):
self.x = 1
one = Class
print(one().x)
Out[1]:
1
正如装饰器返回的是一个函数,我们可以认为元类返回的是一个类。 也正如我在讲装饰器里说过的,装饰器的核心思想,就是装饰函数这个对象、让函数自身代码不变的情况下、增添一些具有普适性的功能。在我看来,元类的核心思想,就是捣鼓类这个对象、使你能对其有着最高程度的控制权。
注意:这绝不一定是个准确的理解!正如 Python界的领袖 Tim Peters 说过:元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。
我的理解仅仅来自于我对元类的应用,它很有可能是非常片面的。不过,由于我的目的是为了让大家知道元类的一种可能是最简单的使用姿势、使大家不至于看到代码里面的 metaclass 就怕,所以还请观众老爷们允许我这个半吊子继续用这个理解讲下去(如果有观众老爷有更深更好的理解、欢迎在评论区里面教我、我会把它们贴在这里的 ( σ'ω')σ)
那么什么叫做最高程度的控制权呢?一个比较简单的栗子就是实现如下需求:定义一个“人”(Person)类,它有三个方法:吃饭、睡觉、续几秒(咦)
定义 Person 的三个子类“小张”(Zhang)、“小王”(Wang)、“小江”(Jiang)
定义“人”的子类“小红”(Hong), 要求他:吃饭像小张一样快
睡觉像小王一样香
续秒像小江一样熟练(喂)
你会怎么去实现呢?如果再要求你把上面三个要求换一换顺序呢?
也许 Python 有许多其它的解决方案、但(我所知道的)最简单的方法、就是使用元类了
幸运的是,虽然元类的思想可能很深,但就这个简单的问题而言、即使我不进行任何说明、相信聪明的观众老爷们也能读懂下面这几块代码
先定义 Person 类:
class Person:
def __init__(self):
self.ability = 1
def eat(self):
print("Eat: ", self.ability)
def sleep(self):
print("Sleep: ", self.ability)
def save_life(self):
print("+ ", self.ability, " s")
再定义三个子类:
class Wang(Person):
def eat(self):
print("Eat: ", self.ability * 2)
class Zhang(Person):
def sleep(self):
print("Sleep: ", self.ability * 2)
class Jiang(Person):
def save_life(self):
print("+ inf s")
然后是最关键的、定义元类(Meta Class):
class Mixture(type):
def __new__(mcs, *args, **kwargs):
name, bases, attr = args[:3]
person1, person2, person3 = bases
def eat(self):
person1.eat(self)
def sleep(self):
person2.sleep(self)
def save_life(self):
person3.save_life(self)
attr["eat"] = eat
attr["sleep"] = sleep
attr["save_life"] = save_life
return type(name, bases, attr)
Done!可能会有观众老爷发现其中有三行代码显得“特别傻”——没错,确实可以用更具有普适性的三行代码来代替我们上面倒数第二到第四行的代码:
class Mixture(type):
def __new__(mcs, *args, **kwargs):
name, bases, attr = args[:3]
person1, person2, person3 = bases
def eat(self):
person1.eat(self)
def sleep(self):
person2.sleep(self)
def save_life(self):
person3.save_life(self)
for key, value in locals().items():
if str(value).find("function") >= 0:
attr[key] = value
return type(name, bases, attr)
抛开所有技术细节而只谈应用的话、其实上面这个栗子可能已经相当足够了。接下来就让我们测试一下这个 Mixture元类吧。先来定义一个小的测试函数,它依次调用 Person 实例吃饭、睡觉、续几秒这三个动作:
def test(person):
person.eat()
person.sleep()
person.save_life()
然后进行两组测试:
class Hong(Wang, Zhang, Jiang, metaclass=Mixture):
pass
test(Hong())
Out[2]:
Eat: 2
Sleep: 2
+ inf s
class Hong(Zhang, Wang, Jiang, metaclass=Mixture):
pass
test(Hong())
Out[3]:
Eat: 1
Sleep: 1
+ inf s
Done!可以看到、我们确实获得了类的高度控制权
可能会有观众老爷想问,如果我直接继承会发生什么事情?就这个栗子而言,如果定义一个类直接继承小王、小张、小江的话,无论按什么顺序继承、结果都会是一样的(猜猜这个结果会是什么? ( σ'ω')σ)
值得一提的是,可以看到我们定义的元类继承自 type、这是因为 Python 自带的元类就是 type
其实即使仅仅基于上述栗子的思想、就已经可以捣鼓出许多有意思的应用了。在我自己实现的神经网络中、我就用了这个思想来把普通 NN 里面的附加层(Dropout、Normalize)扩展成了 CNN 里面的附加层,感兴趣的观众老爷们可以看看这里面的 ConvSubMeta 类
我没有讲太多原理层面的东西,一方面是因为我觉得知道怎么用就好、另一方面是因为我怕乱说话遭报应(……)
希望观众老爷们能够喜欢~
python类的应用_Python · 元类(Meta Class)及其应用相关推荐
- python 元类 详解_Python 元类详解 __new__、__init__、__call__、__metacalss__
了解元类之前,先了解几个魔术方法: __new__.__init__.__call__ __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪 ...
- python元类使用场景_Python元类使用简介
本文概述 Python中的元类是定义类行为方式的类的类.类本身就是元类的实例. Python中的类定义了该类实例的行为.为了更好地理解元类, 需要具有使用Python类的先验经验.在深入研究元类之前, ...
- python元类使用场景_python 元类的使用
class Animal(object): """a class representing an animal""" def __init_ ...
- python元类的使用_Python 元类使用讲解
我要一大群的类都具有一种特点,我怎么给他们加上呢?模板嘛,我从这个模板创建一群类不就OK了?那就需要元类了. 定义一个元类(就是一个类的模板!莫多想,还要记住这是类级别的,不是对象级别的!): 代码如 ...
- python元类_Python元类
python元类 Welcome to today's tutorial on python metaclass. We all know that python is an object orien ...
- Python学习:抽象类以及元类
1.抽象基类: 继承的约束与协议 __doc__ = """ 抽象基类: 继承的约束与协议# 抽象基类 --- 有点java的味道,也有点golang的味道,继承,协议, ...
- python面试题~反射,元类,单例
1 什么是反射?以及应用场景? test.py def f1():print('f1') def f2():print('f2') def f3():print('f3') def f4():prin ...
- python 元类的call_【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理...
原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...
- pythonDay06核心编程part2(类装饰器,元类,垃圾回收,内建属性(属性拦截器),内建函数(fliter,map,reduce,sorted),集合,functools,模块进阶)
我若将死,给孩子留遗言,只留一句话:Repetition is the mother of all learning重复是学习之母.他们将来长大,学知识,技巧.爱情.事业.交流....倘若懂得行动的力 ...
最新文章
- ie在线邮件html编辑器,IE中HTML编辑器的修改与使用.doc
- 各种音频编码方式的对比
- 三种常见中文内码的转换方法
- Linux档案属性与目录配置
- domains where phd is best in business school
- 元宇宙时代,技术长什么样
- 牧马人鼠标g13鼠标宏_经典再升级:达尔优牧马人五代游戏鼠标
- win10 安装docker
- 合并K个有序数组(链表)【字节跳动面试算法题】
- python视频提取关键帧_一种视频关键帧提取算法的制作方法
- ppt使用记录之添加带圈的20以内的数字编号
- maven项目转eclipse工程的命令:eclipse.bat
- python request.get_Python request.get_data方法代码示例
- 基于php的宠物领养系统
- C数据结构排序算法——希尔排序法用法总结(转http://www.cnblogs.com/skywang12345/p/3597597.html)...
- 【ARM编程】ARM介绍
- rails kaminari text modify
- java stl分解_stl文件格式解析代码--java版
- 洛谷 P3373 线段树2
- 官方文件出炉!北京住建委权威解读商住限购
热门文章
- Git学习笔记:如何删除GitHub上的项目
- UEFI+GPT安装Windows8和CentOS双系统
- 【C++】语法小知识
- 【Matlab】方差是偏离均值的程度,那偏离中位数的程度怎么算呢?
- 云炬随笔20161224
- 台湾大学林轩田机器学习基石课程学习笔记3 -- Types of Learning
- 北理工 管理系统计算机仿真作业,20秋北理工《CADCAM原理与应用》--模拟3-答案 更…...
- 解决jquery的多次绑定事件
- Java压缩html
- How to write an operating system