元类

在python中一切皆对象,name我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类

元类是负责产生类的,所以我们学习元类或者定义元类的目的是:为了控制类的产生过程,还可以控制对象的产生过程

类的组成

class People(object):
x = 1
print('from people')
def __init__(self, name, age):
self.name = name
self.age = age def speak(self):
print('from speak')

在用class关键字定义类时,在定义阶段会执行类体中的代码,创建名称空间,所以类由三部分组成

  • 类名class_name:People
  • 基类class_bases:(object,)
  • 类的名称空间class_dic

内置函数 exec()

将字符串中的代码执行,然后把产生的全局名称丢入到global_space字典中,局部名称丢入到local_space字典中

cmd = """
x = 1
global y
y = 10
def __init__(self, name, age):
self.name = name
self.age = age def speak(self):
print('from speak')
"""
global_space = {}
local_space = {}
exec(cmd,global_space,local_space) # 未声明gloabal的变量全是局部变量
print('local:',local_space)
local: {'x': 1, '__init__': <function __init__ at 0x000002C2319EB158>, 'speak': <function speak at 0x000002C2319EB0D0>}

class关键字创建类原理

用class关键字创建一个类,用的默认的元类type

class_name = 'P'  # 类名
class_bases = (object,) # 基类
cmd = """
x = 1
global y
y = 10
def __init__(self, name, age):
self.name = name
self.age = age def speak(self):
print('from speak')
"""
global_space = {}
local_space = {}
exec(cmd,global_space,local_space)
class_dic = local_space # 类的名称空间 P= type(class_name, class_bases, class_dic)
print(P)
<class '__main__.P'>

自定义元类控制类的创建

  • 控制创建类时必须写说明,没写就抛出异常
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
if not class_dict.get('__doc__'):
raise TypeError('必须写说明')
super(Mymeta, self).__init__(class_name, class_bases, class_dict) class People(object, metaclass=Mymeta):
"""
SJFDSFSD
"""
country = 'Chinese' def __init__(self, name, age):
self.name = name
self.age = age def test(self):
print('from f1')
  • 控制创建类时类名不能全为小写,类名全为小写则抛出异常
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
if class_name.islower():
raise TypeError('类名不能全为小写')
super(Mymeta, self).__init__(class_name, class_bases, class_dict) class People(object, metaclass=Mymeta):
country = 'Chinese' def __init__(self, name, age):
self.name = name
self.age = age def test(self):
print('from f1')

自定义元类控制类实例化

类的实例化就是元类的调用,类实例化原理:

  • 先造出一个空对象
  • 为该空对象初始化独有的属性
  • 返回一个初始化好的对象
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
super(Mymeta, self).__init__(class_name, class_bases, class_dict) # 控制类Foo的调用过程,即控制实例化Foo的过程
def __call__(self, *args, **kwargs): # 造一个空对象obj
obj = object.__new__(self) # 调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
self.__init__(obj, *args, **kwargs)
return obj class Foo(object, metaclass=Mymeta):
x = 10 def __init__(self, y):
self.y = y f = Foo(1)
print(f.__dict__)
{'y': 1}

自定义元类后对象属性查找顺序

对象本身-->类-->父类-->父类-->object-->type找不到报错

day24-1 元类的更多相关文章

  1. python之元编程(元类实例)

    本实例是元类实例,功能是记录该的子类的类名,并以树状结构展示子类的类名. RegisterClasses继承自type,提供的功能是在__init__接口,为类创建了childrens的集合,并类名保 ...

  2. python 元类

    转载自  http://blog.jobbole.com/21351/ 类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大 ...

  3. Python语言特性之2:元类

    问题:Python中的元类(metaclasses)是什么?一般使用它干什么? 原地址:http://stackoverflow.com/questions/100003/what-is-a-meta ...

  4. python基础——使用元类

    python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...

  5. [python]python元类

    这两天在看Django框架,里面的filter实现原理搞不明白,最后发现跟python的元类有关系. 原文:http://stackoverflow.com/questions/100003/what ...

  6. Python基础:元类

    一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...

  7. Python中的元类和__metaclass__

    1.什么是元类 元类让你来定义某些类是如何被创建的,从根本上说,赋予你如何创建类的控制权.可以把元类想成是一个类中类,或是一个类,它的实例是其它的类.当某个类调用type()函数时,你就会看到它到底是 ...

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

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

  9. 元类metaClass

    metaClass 实现动态改变对象的能力,这点特别像python(metaClass),Python中类(不是元类)的概念借鉴于Smalltalk groovy demo: class Person ...

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

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

随机推荐

  1. YTU 2801: 用数字造数字(II)

    2801: 用数字造数字(II) 时间限制: 1 Sec  内存限制: 128 MB 提交: 244  解决: 168 题目描述 输入一个3位以上的整数,求其中最大的两个数字之和与最小的数字之和之间的 ...

  2. C++在循环内和循环外定义变量的差异

    原文:http://blog.csdn.net/cashey1991/article/details/45127561 最后总结: 对于使用int等基本数据类型作为循环变量,只要你用的优化方面足够给力 ...

  3. bzoj 1407: [Noi2002]Savage【扩展欧几里得+中国剩余定理】

    首先答案不会很大,所以枚举答案m,于是把问题转为了判定: 关于如何判定: 首先题目中虽然没说但是数据是按照初始洞穴编号排的序,所以并不用自己重新再排 假设当前答案为m,相遇时间为x,野人i和j,那么可 ...

  4. 51nod 1220 约数之和【莫比乌斯反演+杜教筛】

    首先由这样一个式子:\( d(ij)=\sum_{p|i}\sum_{q|j}[gcd(p,q)==1]\frac{pj}{q} \)大概感性证明一下吧我不会证 然后开始推: \[ \sum_{i=1 ...

  5. 安装 Apache Commons Logging API步骤

    下载地址:  http://commons.apache.org/logging/ 

  6. [Usaco2012 Nov]Concurrently Balanced Strings

    Description [Brian Dean, 2012] Farmer John's cows are all of a very peculiar breed known for its dis ...

  7. PHP获取今天内的时间 今天开始和结束的时间戳

    $t = time(); $start = mktime(0,0,0,date("m",$t),date("d",$t),date("Y", ...

  8. 通过Fiddler监控Java应用发送请求及相应数据

    Fiddler可以很好的监控浏览器发送的各种请求及响应数据,对于JAVA程序默认情况下是无法监控的,但实际需求中需要监控JAVA程序发送HTTP请求及返回数据是否正确. Fiddler默认配置的监听端 ...

  9. NDK(10)Android.mk各属性简介,Android.mk 常用模板--未完

    参考 : http://blog.csdn.net/hudashi/article/details/7059006 1. Android.mk简介 Android.mk文件是GNU Makefile的 ...

  10. zojDakar Rally(01背包)

    01背包 加上每次更新解题数目最多 总用时最少 因为要保证用时最少,要先把时长由小到大排序. 没排序 WA了几小时..链接 #include <iostream> #include< ...