[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)难以理解.他知道这肯定和自省有关,但仍然觉 ...
随机推荐
- html5 微信真机调试方法vConsole
html5 微信真机调试方法 vConsolehttps://blog.csdn.net/weixin_36934930/article/details/79870240
- Hazel,自动整理文件,让你的 Mac 井井有条
原文地址 https://sspai.com/post/35225 让我们从实际需求出发,看看问题出在哪里,并在此基础上认识和学习使用 Hazel. 电脑随着使用时间的增长,其中的文件也在疯狂的增长, ...
- C# IV: 数据库基础操作2
需上一篇C# III:数据库基础操作 另外一个经常碰到的数据库操作是,单次执行多个SQL语句,譬如,一次性插入多条数据. 方法一,拼凑长SQL语句 拼凑长SQL语句实际上是String的操作.如下示例 ...
- [Bootstrap] Bootstrap学习笔记
1.因为bootstrap用到了html5的特性,为了正常使用,需要在最开头加上<!DOCTYPE html> 2.Bootstrap需要JQuery才能正常工作,所以需要导入jquery ...
- PowerMock学习之PoweMock的入门(二)
前言 在上一篇<PowerMock学习之PoweMock的入门(一)>文章中,已经简单提及一些关于powermock的用法,但是入门还未完,我还要坚持把它学习并坚持更新到博客中. Mock ...
- nyoj 208 + poj 1456 Supermarket (贪心)
Supermarket 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 A supermarket has a set Prod of products on sal ...
- PHP的global和$GLOBALS的区别
global是关键字,通常添加在变量前,可以使变量的作用域为全局. $GLOBALS预定义的超全局变量,把变量扔到里面一样可以变成全局变量. $GLOBALS 是一个关联数组,每一个变量为一个元素,键 ...
- TreeMap的源码学习
TreeMap的源码学习 一).TreeMap的特点 根据key值进行排序. 二).按key值排序的两种排序算法实现 1).在构造方法中传入比较器 public TreeMap(Comparator& ...
- Python3 之 with语句(高效、便捷)
在实际的编码过程中,有时有一些任务,需要事先做一些设置,事后做一些清理,这时就需要python3 with出场了,with能够对这样的需求进行一个比较优雅的处理,最常用的例子就是对访问文件的处理. 文 ...
- 小白学习python第一天,Pycharm破解与用法(持续更新)
目录 Pycharm安装与破解及汉化 Pycharm安装 Pycharm破解 Pycharm汉化 Pycharm使用 添加作者.时间等信息 补充 @ Pycharm安装与破解及汉化 本人最近开始找到了 ...