python 面向对象十二 元类
一、类也是对象
只要使用关键字class,Python解释器在执行的时候就会创建一个对象。下面的代码段:
class ObjectCreator(object):
pass
将在内存中创建一个对象,名字就是ObjectCreator。这个对象(类)自身拥有创建对象(类实例)的能力。
它的本质仍然是一个对象,于是乎你可以对它做如下的操作:
1) 你可以将它赋值给一个变量
2) 你可以拷贝它
3) 你可以为它增加属性
4) 你可以将它作为函数参数进行传递
>>> class ObjectCreator(object):
... pass
...
>>> print(ObjectCreator) # 可以打印,因为也是个对象
<class '__console__.ObjectCreator'>
>>> print(type(ObjectCreator))
<class 'type'>
>>> def echo(o):
... print(o)
...
>>> echo(ObjectCreator) # 当做参数
<class '__console__.ObjectCreator'>
>>> hasattr(ObjectCreator, 'new_attribute')
False
>>> ObjectCreator.new_attribute = 'foo' # 增加属性
>>> hasattr(ObjectCreator, 'new_attribute')
True
>>> ObjectCreator.new_attribute
'foo'
>>> ObjectCreatorMirror = ObjectCreator # 赋值给变量
>>> ObjectCreatorMirror()
<__console__.ObjectCreator object at 0x0000000002CB38D0>
二、使用type动态创建类
type可以接受一个类的描述作为参数,然后返回一个类。type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
 >>> MyShinyClass = type('MyShinyClass', (), {})
 >>> MyShinyClass
 <class '__console__.MyShinyClass'>
 >>> MyShinyClass()
 <__console__.MyShinyClass object at 0x0000000002CB3978>
 >>> MyShiny = type('MyShinyClass', (), {})
 >>> MyShiny
 <class '__console__.MyShinyClass'>
 >>> MyShinyClass
 <class '__console__.MyShinyClass'>
>>> Foo = type('Foo', (), {'bar': True})
>>> Foo.bar
True
>>> f = Foo()
>>> f.bar
True
 >>> FooChild=type('FooChild', (Foo,),{})
 >>> FooChild
 <class '__console__.FooChild'>
 >>> FooChild.bar
 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
三、元类
元类就是用来创建类的“东西”。元类创建类对象,类对象创建实例对象。
type可以动态创建类,是因为函数type实际上是一个元类。type就是Python在背后用来创建所有类的元类。
四、metaclass
在用 class 语句自定义类时,默认 metaclass 是 type,我们也可以指定 metaclass 来创建类。
五、自定义元类
元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。
 class UpperAttrMetaclass(type):
     def __new__(cls, name, bases, dct):
         print(name, bases, dct)
         attrs = ((name, value)
                  for name, value in dct.items() if not name.startswith('__'))
         uppercase_attr = dict((name.upper(), value) for name, value in attrs)
         return super(UpperAttrMetaclass,
                      cls).__new__(cls, name, bases, uppercase_attr)
 class Foo(object, metaclass=UpperAttrMetaclass):
     bar = 'bip'
 print(hasattr(Foo, 'bar'))
 # 输出: False
 print(hasattr(Foo, 'BAR'))
 # 输出:True
 f = Foo()
 print(f.BAR)
 # 输出:'bip'
sensitive_words_list = ['asshole', 'fuck', 'shit'] def detect_sensitive_words(st):
'''检测敏感词汇'''
words_detected = list(filter(
lambda word: word in st.lower(), sensitive_words_list))
if words_detected:
raise NameError('Sensitive words {0} detected in the string "{1}".'
.format(', '.join(map(lambda s: '"%s"' % s,
words_detected)), st)
) class CleanerMeta(type): def __new__(cls, class_name, bases, attrs):
detect_sensitive_words(class_name) # 检查类名 map(detect_sensitive_words, attrs.keys()) # 检查属性名 print("Well done! You are a polite coder!") # 如无异常,输出祝贺消息 return super(CleanerMeta, cls).__new__(cls, class_name, bases, attrs)
# 重要!这行一定不能漏!!这回调用内建的类构造器来构造类,否则定义好的类将会变成 None class APIBase(object, metaclass=CleanerMeta): pass a = APIBase()
print(a.__class__)
print(a.__class__.__class__)
print(a.__class__.__class__.__class__)
输出:
Well done! You are a polite coder!
<class '__main__.APIBase'>
<class '__main__.CleanerMeta'>
<class 'type'>
python 面向对象十二 元类的更多相关文章
- python 面向对象进阶之元类metaclass
		一:知识储备 exec exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定,默认为globals() 参数三:局部作用域(字典形式),如果不指定,默认为local ... 
- Python面向对象篇之元类,附Django Model核心原理
		关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ... 
- 【转】python面向对象中的元类
		type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ... 
- python 面向对象编程 之 元类
		元类是类的类,使我们自定义的类,即我们用class定义类本质就是元类,是类的模板 四步走: 一:控制class定义类的过程 1.先拿到类名 2.在拿到基类 3.执行类体代码,得到名称空间的dict 4 ... 
- 神级程序员通过两句话带你完全掌握Python最难知识点——元类!
		千万不要被所谓"元类是99%的python程序员不会用到的特性"这类的说辞吓住.因为 每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生 ... 
- Python入门之Python的单例模式和元类
		一.单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在. 当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上 ... 
- 初学 Python(十二)——高阶函数
		初学 Python(十二)--高阶函数 初学 Python,主要整理一些学习到的知识点,这次是高阶函数. #-*- coding:utf-8 -*- ''''' 话说高阶函数: 能用函数作为参数的函数 ... 
- Lua面向对象之二:类继承
		1.类继承 ①代码 Sharp = { } --① 父类 function Sharp:new() local new_sharp = { } self.__index = self --②,self ... 
- Python进阶(十二)----re模块
		Python进阶(十二)----re模块 一丶re模块  re模块是python将正则表达式封装之后的一个模块.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. #正则表达式: ... 
随机推荐
- BeagleBone Black Industrial 进阶设置(性能优化以及延长板载eMMC存储寿命)
			前言 原创文章,转载引用务必注明链接.水平有限,欢迎指正. 本文使用markdown写成,为获得更好的阅读体验,推荐访问我的博客原文: http://www.omoikane.cn/2016/09/1 ... 
- JavaScript - 正则表达式解惑
			正则表达式手册: http://tool.oschina.net/uploads/apidocs/jquery/regexp.html 正则表达式测试地址: http://tool.chinaz.co ... 
- HDU oj  开门人与关门人
			题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1234 #include<stdio.h> #include<string.h> ... 
- 生成可重集的排序 (白书P184)
			#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> us ... 
- Oracle创建JOB定时任务
			--- DECLARE JOB NUMBER;BEGIN DBMS_JOB.SUBMIT( JOB=>JOB, WHAT=>'CTABLE_T ... 
- HDU 1284 钱币兑换问题 (完全背包)
			钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ... 
- java的多态以及重载,重写,前期绑定,后期绑定
			多态的定义: 一个类实例的相同方法在不同情形有不同表现形式.多态机制使具有不同内部结构的对象可以共享相同的外部接口.这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通 ... 
- 项目Alpha冲刺(团队10/10)
			项目Alpha冲刺(团队10/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 22160041 ... 
- ios如何获取手机的网络状态和运营商名称
			本文转载至 http://blog.csdn.net/justinjing0612/article/details/38313747 以前获取手机的网络状态和运营商名称都是似有API, 现在我们可以大 ... 
- poj 3017 Cut the Sequence(单调队列优化DP)
			Cut the Sequence \(solution:\) 这道题出的真的很好,奈何数据水啊! 这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看 ... 
