元类和动态类

本篇笔记学习自:Improve Your Python: Metaclasses and Dynamic Classes With Type

  • type()的使用
>>> type(1)
<class 'int'>
>>> type('foo')
<class 'str'>
>>> type(3.0)
<class 'float'>
>>> type(float)
<class 'type'>
  • type的类型?
    上面的 type(float) 为什么是<class 'type'>呢?我们再来看一个例子:
>>> class Foo(object):
...     pass
...
>>> type(Foo)
<class 'type'>

还有这个:

>>> type(type)
<class 'type'>

type是所有类型的类型,包括它自己。type是一个元类,或者是一个创建所有类的东西。

  • 创建自己的元类

Just like regular classes, metaclasses can be user-defined. To use it, you set a class's metaclass attribute to the metaclass you built. A metaclass can be any callable, as long as it returns a type. Usually, you'll assign a class's metaclass to a function that, at some point, uses a variant of type we've not yet discussed: the three parameter variety used to create classes.

就像普通的类,元类也可以是用户自定义的。使用自定义元类时,你需要设置一个类的metaclass属性为你创建的那个元类。元类可以是任何可调用的函数,只要它返回一种类型。

当我们写下下面的代码就是创建类的过程,首先解释器会检查是否有metaclass这个属性,没有就调用type来创建类(类也是对象)。

class Foo(Bar):
  pass

现在的问题就是,你可以在metaclass中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。

  • type的缺点
    当我们调用type并且传入三个参数的时候——type(name, bases, dict)创建一种新的类型。
    以下的两份代码作用是相同的,运行后,Foo都指向了一个继承自object的类:
class Foo(object):
    pass
Foo = type('Foo', (), {})

添加方法:

def always_false(self):
    return False

Foo.always_false = always_false

或者可以这样子做:

Foo = type('Foo', (), {'always_false': always_false})

类的继承:

FooBar = type('FooBar', (Foo), {})
  • 这有什么鬼用?
    虽然不经常用到,但是在一些场合,用type来创建类比较合适,比如在一些需要动态创建类的场合,只有程序允许起来,我们才有足够的信息知道要怎么去创建类,这些场合用type来动态创建类比较合适。

元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过在模块级别设定metaclass。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。

  • 自定义元类的例子——将类的属性都改为大写

元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的
类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通
过在模块级别设定metaclass。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有
的属性都改成大写形式就万事大吉了。

首先我们需要一个元类:

# 元类会自动将你通常传给‘type’的参数作为自己的参数传入
def upper_attr(future_class_name, future_class_parents, future_class_attr):
    '''返回一个类对象,将属性都转为大写形式'''
     # 选择所有不以'__'开头的属性
     attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
     #  将它们转为大写形式
    uppercase_attr = dict((name.upper(), value)  for name, value  in attrs)
     #  通过 'type' 来做类对象的创建
     return type(future_class_name, future_class_parents, uppercase_attr)

模块级别地设置metaclass

__metaclass__ = upper_attr   #   这会作用到这个模块中的所有类
class Foo(object):
     #  我们也可以只在这里定义 __metaclass__ ,这样就只会作用于这个类中
    bar = 'bip'
    print
    hasattr(Foo, 'bar')
    #  输出 : False
    print
    hasattr(Foo, 'BAR')
    #  输出 :True
    f = Foo()
    print
    f.BAR
    #  输出 :'bip'

拓展阅读:
1.stackoverflow上面的问答
2.上面链接回答的翻译

类也是对象,创建类的就是元类。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,673评论 18 139
  • 前言 第十二篇了,撸起袖子,就是干。 目录 一、Python 中类也是对象 在了解元类之前,我们先进一步理解 Py...
    GitHubClub阅读 761评论 0 7
  • { "Unterminated string literal.": "未终止的字符串文本。", "Identifi...
    栗子雨阅读 7,891评论 0 3
  • 1.元类 1.1.1类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段。在Python中这...
    TENG书阅读 1,275评论 0 3
  • 一元类 1类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段。在Python中这一点仍然成...
    五行缺觉阅读 1,061评论 0 1