[TimLinux] Python 再谈元类 metaclass
本博文通过对以下链接进行理解后,编写。
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的更多相关文章
- Python中的元类(metaclass)
推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
- python中的元类metaclass
本文是一个转载的,因为原文写的太好了,所以直接copy过来吧. 原文请看:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上 很热的帖子.提问 ...
- 深刻理解Python中的元类metaclass(转)
本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...
- 深刻理解Python中的元类(metaclass)
译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...
- [转] 深刻理解Python中的元类(metaclass)
非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...
- 深刻理解Python中的元类(metaclass)【转】
译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...
- 深入理解Python中的元类(metaclass)
原文 译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍 ...
- python——深刻理解Python中的元类(metaclass)
译注:这是一篇在Stack overflow上 很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉 ...
随机推荐
- css 完美垂直居中解决方案兼容ie8以上等其他浏览器
css 完美垂直居中解决方案兼容ie8以上等其他浏览器 <pre><!DOCTYPE html><html><head> <title>DI ...
- node.js 需要注意知识点
复习node.js 需要注意知识点--(重点) 2.1:参数传递获取造型 客户端脚手架(发) (参数传递) node.js(收) -发ajax this.axios.get(" ...
- tcpdump抓包工具
tcpdump抓包工具 一:TCPDump介绍 TcpDump可以将网络中传送的数据包的"头"完全截获下来提供分析.它支持针对网络层.协议.主机.网络或端口的过滤,并提供and ...
- 痞子衡嵌入式:串行EEPROM接口事实标准及SPI EEPROM简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是EEPROM接口标准及SPI EEPROM. 痞子衡之前写过一篇文章 <SLC Parallel NOR简介>,介绍过并行N ...
- T-SQL, Part I: LIKE Pattern
The basic usage of LIKE pattern: %: it would be placed at the end and/or the beginning of a string. ...
- Jquery 处理返回的 Json 数组
Jquery 处理返回的 Json 数组 <script> for (var i = 0; i < photos.length; ++ i) { console.log(photos ...
- 802.11r协议理解
首先阅读了相关协议内容整理出了如下的802.11r时序图所谓基础,然后会详细理解其中的每一个步骤:
- 领扣(LeetCode)两句话中的不常见单词 个人题解
给定两个句子 A 和 B . (句子是一串由空格分隔的单词.每个单词仅由小写字母组成.) 如果一个单词在其中一个句子中只出现一次,在另一个句子中却没有出现,那么这个单词就是不常见的. 返回所有不常用单 ...
- hopper逆向的伪代码令人大跌眼镜
网上介绍hopper有逆向伪代码的文章很多,并以为其是万能而且cool B的.但是并没有人去求证hopper的逆向伪代码参考系数(参考价值,大家做过开发都清楚明白,有些功能看起来很花很cool但不实用 ...
- 查看k8s中etcd数据
#查看etcd pod kubectl get pod -n kube-system | grep etcd #进入etcd pod kubectl exec -it -n kube-system e ...