本博文通过对以下链接进行理解后,编写。

https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

1. 类

类也是对象,具有对象的特点:

  • 你可以将它赋值给变量
  • 你可以copy它
  • 你可以给它添加属性
  • 你可以把它作为函数参数进行传递

类定义语法:

class Foo(object): pass

说明:
1. 这是一种语法糖,一种对类对象的声明方式,与def func, a = 123, 本质上没有区别,都是为了创建一个对象。
2. 对象的创建都关联到一个类,比如 a = 123 关联的类是 'int', b = 'hello' 关联的类是 'str', def func(): pass 关联的类是 'function', 而 class Foo(object): pass 关联的类就是元类 'metaclass', 默认为 'type'

对象重要特性:动态创建,你可以随时随地在你需要的地方创建对象,类也可以动态创建。

2. 动态创建

根据函数参数来创建类,看起来像是类工厂,但是动态性不够。

def choose_class(name):
if name == 'foo':
class Foo(object): pass
return Foo # return the class, not an instance
else:
class Bar(object): pass
return Bar >>> MyClass = choose_class('foo')
>>> print(MyClass) # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print(MyClass()) # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>

真正的动态创建,是通过元类(默认type类构造函数)来创建:

# 创建类
>>> Foo = type('Foo', (), {'bar':True})
>>> print(Foo)
<class '__main__.Foo'>
>>> print(Foo.bar)
True
>>> f = Foo()
>>> print(f)
<__main__.Foo object at 0x8a9b84c>
>>> print(f.bar)
True # 创建子类
>>> FooChild = type('FooChild', (Foo,), {})
>>> print(FooChild)
<class '__main__.FooChild'>
>>> print(FooChild.bar) # bar is inherited from Foo
True # 给子类分配实例方法
>>> def echo_bar(self):
... print(self.bar)
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True # 再分配一个实例方法
>>> def echo_bar_more(self):
... print('yet another method')
...
>>> FooChild.echo_bar_more = echo_bar_more
>>> hasattr(FooChild, 'echo_bar_more')
True

3. 动态创建语法糖

为此 python 语言本身又提供了一个语法糖,在声明类的时候,就指定后台自动创建这个类的方法,方法就是 __metaclass__ 变量(python2.7), metaclass=xxx(python3.x)。示例:

# 文件保存为:mymetaclass.py
# 执行 python2 metaclass.py def upper_attr(name, parents, attributes):
new_attributes = {}
for n, v in attributes.items():
if not n.startswith('__'):
uppercase_attr[n.upper()] = v
else:
uppercase_attr[n] = v
return type(name, parents, new_attributes) __metaclass__ = upper_attr # py3这个无法工作 class Foo(): # py3,需要使用这个语法:class Foo(metaclass=upper_attr):
bar = 'bip' def __init__(self):
self.link = "link"
def func(self):
print("Enter func") # 类属性,函数都被转换为大写了
print(hasattr(Foo, 'bar')) # False
print(hasattr(Foo, 'BAR')) # True print(hasattr(Foo, 'func')) # False
print(hasattr(Foo, 'FUNC')) # True # 元类转换了类属性,但是没有转换实例属性, __init__ 内的变量没有被转换
print(hasattr(Foo, 'link')) # False
print(hasattr(Foo, 'LINK')) # False print(hasattr(Foo(), 'link')) # True
print(hasattr(Foo(), 'LINK')) # False

以上使用的是函数作为元类实现方式,也可以直接使用类作为元类,元类中实现的是 __new__ 方法,在生成类对象之前会被调用的方法即为 __new__ 方法。而不是 __init__ 方法, __init__ 方法是操作的类对象返回之后,创建的实例对象的初始化行为。

# metaclass 控制的是 __new__ 方法,而不是 __init__ 方法
class UpperAttrMetaclass(type):
def __new__(cls, name, parents, attributes):
new_attributes = {}
for n, v in attributes.items():
if not n.startswith('__'):
new_attributes[n.upper()] = v
else:
new_attributes[n] = v
#以下返回值推荐使用super方法,对当前示例两者效果相同,使用super可以使
#当前元类能够继承其他元类
#return type.__new__(cls, name, parents, new_attributes)
#return super(UpperAttrMetaclass, cls).__new__(cls, name, parents, new_attributes)
return type.__new__(cls, name, parents, new_attributes) class Foo(object, metaclass=upper_attr):
bar = 'bip'
def __init__(self):
self.link = "link"
def func(self):
print("Enter func") # 效果与使用函数的元类实现一致!!!
# 类属性,函数都被转换为大写了
print(hasattr(Foo, 'bar')) # False
print(hasattr(Foo, 'BAR')) # True print(hasattr(Foo, 'func')) # False
print(hasattr(Foo, 'FUNC')) # True # 元类转换了类属性,但是没有转换实例属性, __init__ 内的变量没有被转换
print(hasattr(Foo, 'link')) # False
print(hasattr(Foo, 'LINK')) # False print(hasattr(Foo(), 'link')) # True
print(hasattr(Foo(), 'LINK')) # False

4. 写作最后

99%用户用不到元类,所以大家洗洗睡吧,了解就行。

[TimLinux] Python 再谈元类 metaclass的更多相关文章

  1. Python中的元类(metaclass)

    推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...

  2. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  3. python中的元类metaclass

    本文是一个转载的,因为原文写的太好了,所以直接copy过来吧. 原文请看:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上 很热的帖子.提问 ...

  4. 深刻理解Python中的元类metaclass(转)

    本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...

  5. 深刻理解Python中的元类(metaclass)

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  6. [转] 深刻理解Python中的元类(metaclass)

    非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...

  7. 深刻理解Python中的元类(metaclass)【转】

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  8. 深入理解Python中的元类(metaclass)

    原文 译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍 ...

  9. python——深刻理解Python中的元类(metaclass)

    译注:这是一篇在Stack overflow上 很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉 ...

随机推荐

  1. linux 安装swoole扩展方法

    linux 安装swoole扩展方法 wget https://github.com/swoole/swoole-src/archive/v1.9.23.tar.gz接下去就不说了 说明下 下载swo ...

  2. 学Linux到底学什么?

    前言 我们常常听到很多人说要学学Linux或者被人告知说应该学学Linux,那么学Linux到底要学什么? 为什么要学Linux 在回答学什么之前,我们先看看为什么要学.首先我们需要认识到的是,很多服 ...

  3. keeplived离线安装openssl-devel依赖包

    转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1434 由于公司业务并发比较高需要高可用使用LVS keeplived.在linux系统ce ...

  4. ffmpeg centos yum安装

    CentOS 6&7安装ffmpeg   CentOS 6和7安装方法是不一样的,下面分别说明: 安装前都需要先安装epel扩展源 yum -y install epel-release ce ...

  5. jenkins手把手教你从入门到放弃01-jenkins简介(详解)

    一.简介 jenkins是一个可扩展的持续集成引擎.持续集成,也就是通常所说的CI(Continues Integration),可以说是现代软件技术开发的基础.持续集成是一种软件开发实践, 即团队开 ...

  6. a 标签添加 onclick 事件

    a 标签添加 onclick 事件 <a href="javascript:void(0);" οnclick="js_method()">点击&l ...

  7. 【Java】面向对象之多态

    生活中,比如动物中跑的动作,小猫.小狗和大象,跑起来是不一样的.再比如飞的动作,昆虫.鸟类和飞机,飞起来也是不一样的.可见,同一类的事物通过不同的实际对象可以体现出来的不同的形态.多态,描述的就是这样 ...

  8. 在 Windows 上 安装 Oracle 11g Xe

    去oracle官网下载 https://www.oracle.com/database/technologies/xe-prior-releases.html 点击下载: Oracle Databas ...

  9. basename 和 dirname

    basename将目录路径去掉,返回文件的实际文件名(此处也可以是最后一级目录).如与$0一起 if [ $? -eq 0 ]; then cd - ; mv `basename $0` test1. ...

  10. 浅谈Linux中的各种锁及其基本原理

    本文首发于:https://mp.weixin.qq.com/s/Ahb4QOnxvb2RpCJ3o7RNwg 微信公众号:后端技术指南针 0.概述 通过本文将了解到如下内容: Linux系统的并行性 ...