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 类

我没有讲太多原理层面的东西,一方面是因为我觉得知道怎么用就好、另一方面是因为我怕乱说话遭报应(……)

希望观众老爷们能够喜欢~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值