
第七节 使用元类
发布日期:2021-05-10 05:00:13
浏览次数:16
分类:精选文章
本文共 2785 字,大约阅读时间需要 9 分钟。
使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。 当Python解释器载入hello模块时,就会依次执行该模块的所有语句,执行结果就是动态创建出一个Hello的class对象,测试如下: >>> from hello import Hello >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class 'hello.Hello'> type()函数可以查看一个类型或变量的类型,Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello。 ************************************************************************ 我们说class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。 type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类, 要创建一个class对象,type()函数依次传入3个参数: 1.class的名称; 2.继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法; 3.class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。 >>> def fn(self, name='world'): # 先定义函数 ... print('Hello, %s.' % name) ... >>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class metaclass 除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。 metaclass,直译为元类,简单的解释就是: 当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。 但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。 连接起来就是:先定义metaclass,就可以创建类,最后创建实例。 所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。 metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。 用到的时候再学 数据库接口 type可以像这样工作: type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值)) 比如下面的代码: Python >>> class MyShinyClass(object): … pass 可以手动像这样创建: Python >>> MyShinyClass = type('MyShinyClass', (), {}) # 返回一个类对象 >>> print MyShinyClass <class '__main__.MyShinyClass'> >>> print MyShinyClass() # 创建一个该类的实例 <__main__.MyShinyClass object at 0x8997cec> 到底什么是元类???? 元类就是用来创建这些类(对象)的,元类就是类的类 type就是Python在背后用来创建所有类的元类。 __metaclass__属性 你可以在写一个类的时候为其添加__metaclass__属性。 class Foo(object): __metaclass__ = something… […] 如果你这么做了,Python就会用元类来创建类Foo。 Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类。 class Foo(Bar): pass Python做了如下的操作: Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。 现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。 自定义元类 元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过在模块级别设定__metaclass__。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。 元类的主要用途是创建API。一个典型的例子是Django ORM。它允许你像这样定义: class Person(models.Model): name = models.CharField(max_length=30) age = models.IntegerField() 但是如果你像这样做的话: guy = Person(name='bob', age='35') print guy.age 这并不会返回一个IntegerField对象,而是会返回一个int,甚至可以直接从数据库中取出数据。这是有可能的,因为models.Model定义了__metaclass__, 并且使用了一些魔法能够将你刚刚定义的简单的Person类转变成对数据库的一个复杂hook。Django框架将这些看起来很复杂的东西通过暴露出一个简单的使用元类的API将其化简,通过这个API重新创建代码,在背后完成真正的工作。发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月03日 06时48分53秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Vue 实现移动端左右滑动切换
2021-05-10
交换机基础知识 - 从零开始学习
2021-05-10
Kali Linux 内网渗透教程 - ARP欺骗攻击 | 超详细
2021-05-10
Unable to find vcvarsall.bat build_ext
2021-05-10
搞懂线程和进程的关系及区别
2021-05-10
java如何实现任意两个值交换 数组为例(值传递和地址传递)
2021-05-10
2020Java程序设计基础(华东交通大学)章节测试免费满分答案
2021-05-10
嵌入式流水线以及数据存储的大小端
2021-05-10
PS入门小技巧8
2021-05-10
C/C++初学之创建项目
2021-05-10
C/C++语法规则
2021-05-10
爱生气的书店老板
2021-05-10
什么是JDBC?
2021-05-10
ENSP模拟器
2021-05-10
基础数据结构之字符串
2021-05-10
windows下命令行模式中cd命令无效的解决办法
2021-05-10
Firing POJ - 2987(最大权闭合图)
2021-05-10
监控时代,那无处安放的隐私
2021-05-10
为汽车新零售注入活力,瓜子二手车严选直卖店落地长沙
2021-05-10