元类

python一切皆对象,类实际上也是一个一个对象

类是一个对象,那他一定是由一个类实例化得到,这个类就叫元类

如何找元类

class Person:
def __init__(self, name):
self.name = name
def score(self):
print('分数是100') print(type(Person)) #<class 'type'> #所有类的元类都是type

常规的class 类名 会把类构造出来,实际上是元类实例化产生类这个对象,

Person类是对象,一定是由一个类实例化产生的,所以type()产生对象,调用__init__方法,看源码里面需要穿三个参数

**class底层实现原理是: type(object_or_name, bases, dict), **

  1. object_or_name: 类的名字,是个字符串

  2. bases: 是它的所有父类,基类

  3. dict: 名称空间是一个字典

#通过type来直接产生类,不用class关键字
l = {}
exec{'''
school='oldboy'
def __init__(self, name):
self.name = name
def score(self):
print('分数是100')
''', {}, l}
def __init__(self, name):
self.name=name Person = type('Person', (object,), l) # 等同于生成一个Person类,其中具有school属性,对象有name属性,有score方法 ### 下面几句可以生成一个Person类,与上面的语句实现相同的功能
#def __init__(self, name):
#self.name = name
#Person = type('Person', (object,), {'school':'
# oldboy','__init__':__init__})

自定义元类

来控制类的产生,可以控制类名,可以控制类的继承关系 ,控制类的名称空间

自定义元类必须继承type,写一个类继承type,这种类都叫元类

class Mymeta(type):
def __init__(self, name, bases,dic):
#练习一:加限制 控制类名必须以sb 开头
if not name.startswith('sb'):
raise Exception(’类名没有以sb开头‘)# 如果不是以sb开头,就会抛异常
#练习二:类必须加注释
print(self.__dict__['__doc__']) # 有注释的话会把注释打印出来
#metaclass=Mymeta 指定这个类生成的时候,用自己写的Mymeta这个元类 class Person(object,metaclass=Mymeta):
'''
注释
'''
school = 'oldboy'
def __init__(self, name):
self.name = name
def score(self):
print('分数是100') p = Person('nick')
  1. 自定义一个元类,控制类产生,类的名称空间必须有name字段才能创建成功,否则失败
class Mymeta(type):
def __init__(self, x, y, z):
for k, v in self.__dict__.items():
print(k,v)
# print(self.__dict__)
if 'name' not in self.__dict__.values() and 'name'not in self.__dict__.keys():
raise Exception('你的类没有“name”这个字段')
else:
print('名称空间已经存在"name"')
  1. 自定义一个元类,定义一个类,继承字典,使其具备 点取值和赋值功能,通过元类控制对象的产生,把所有对象的属性都放在attr字典中,属性全部删除

例如di=Mydict(name='lqz', age=18) di的名称空间中没有name和age属性,但是有attr字典属性,字典包含{'name':'lqz', 'age':18} (待修改)

class Mymeta(type):
def __call__(self, name, age):#要有返回值
obj = object.__new__(self)
obj.__dict__['attr'] = {'name':name,'age':age}
return obj
class Person(metaclass=Mymeta):
def __init__(self,name,age):
self.name = name
self.age = age
p = Person('lje', 18)
print(p.__dict__)
print(p.attr['name']) '''
{'attr': {'name': 'lje', 'age': 18}}
lje
''' ##延伸(对类名称空间中的属性单独放到attr字典里,但是该字典依然在类名称空间的字典里)
class Mymeta(type):
def __init__(self,name,bases,dic):
pass
def __new__(cls, name,bases,dic):#要有返回值
dic2={'attr':{}}#单独列一个字典,用于盛放类的属性
for k,v in dic.items():
if not k.startswith('__'):#如果key值以__开头,就把大拿出来放到dic2中
dic2['attr'][k]=v
print('-------',dic2)
return type.__new__(cls,name,bases,dic2)#把dic2当成名称空间返回,但是类的名称空间还是原来的dic,只不过属性放到attr小字典里了
class Person(metaclass=Mymeta);#Person=Mymeta(name,bases,dic) 调用type的__call__,内部调用了Mymeta.__new__,又调用了Mymeta的__init__
school = 'Tshinghua'
age = 10
def __init__(self, name, age):
self.name = name
self.age = age
print(Person.__dict__)
print(Person.attr['school']) '''
------- {'attr': {'school': 'oldboy', 'age': 10}}
{'attr': {'school': 'oldboy', 'age': 10}, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
Tshinghua
'''

面向对象高级B(元类)的更多相关文章

  1. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  2. python 面向对象进阶之元类metaclass

    一:知识储备 exec exec:三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定,默认为globals() 参数三:局部作用域(字典形式),如果不指定,默认为local ...

  3. C++面向对象高级编程(五)类与类之间的关系

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 本节主要介绍一下类与类之间的关系,也就是面向对象编程先介绍两个术语 Object Oriented Programming   OOP面向对象编 ...

  4. 【转】python面向对象中的元类

    type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...

  5. python 面向对象编程 之 元类

    元类是类的类,使我们自定义的类,即我们用class定义类本质就是元类,是类的模板 四步走: 一:控制class定义类的过程 1.先拿到类名 2.在拿到基类 3.执行类体代码,得到名称空间的dict 4 ...

  6. python 面向对象十二 元类

    一.类也是对象 只要使用关键字class,Python解释器在执行的时候就会创建一个对象.下面的代码段: class ObjectCreator(object): pass 将在内存中创建一个对象,名 ...

  7. CSIC_716_20191129【面向对象高级----反射、类的内置方法(魔法方法)、单例模式】

    反射 反射是通过'字符串'对 对象的属性进行操作,反射有四个内置的方法. hasattr 通过字符串 判断对象的属性或者方法是否存在 getattr 通过字符串  获取对象的属性或者方法        ...

  8. 【IOS 开发】Objective - C 面向对象高级特性 - 包装类 | 类处理 | 类别 | 扩展 | 协议 | 委托 | 异常处理 | 反射

    一. Objective-C 对象简单处理 1. 包装类 (1) 包装类简介 NSValue 和 NSNumber : -- 通用包装类 NSValue : NSValue 包装单个 short, i ...

  9. python面向对象高级:定制类

    Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类. 比如: __str__ 与__repr____iter____getitem____call__ __str__ 与__r ...

  10. Python实用笔记 (26)面向对象高级编程——定制类

    Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类.以下是集中常见的定制方法: 怎么才能打印得好看呢?只需要定义好__str__()方法,返回一个好看的字符串就可以了: _ ...

随机推荐

  1. C# socket ipv6初体验

    Server: serverSocket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp) ...

  2. 关于App收集个人信息基本规范,这里公开征求你的意见!

    关于App收集个人信息基本规范,这里公开征求你的意见! https://www.thepaper.cn/newsDetail_forward_4122573 以后国家开始规范App收集个信息基本规范, ...

  3. intelliJ 社区版-找不到 plugins选项

    丢人了... 今天 在intelliJ社区版上面找不到 plugins 选项了, 其实是有的,我看的是项目的 settings 当然没有了, (1)如果直接点击File==> 这样就是没有plu ...

  4. gulp的初阶使用方法(转)

    安装好gulp之后接下来就是使用了,此文主要介绍一些前端开发时常用的一些插件及其用法 http://www.imooc.com/article/tag/26/hot/12插件安装 安装本地服务器插件: ...

  5. C# 直接清空缓存方法

    注意要使用 HttpContext.Current.Cache.Remove(cacheKey); 不能使用 HttpRuntime.Cache[cacheKey]=null;

  6. Linux 安装Mysql1.8【yum安装】

    .下载mysql的yum源 wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm2.安装yum源yum lo ...

  7. hibernate中many-to-one的not-found属性和@notfound注解

    如果在Hibernate项目里面配了很多many-to-one的关联,即使后台在查询数据时已经作了健全性判断,但还是会经常抛出对象找不到异常:org.hibernate.ObjectNotFoundE ...

  8. TortoiseSVN客户端更改新的URL和账号

    一: 变更SVN地址 右键(TortoiseSVN) → Relocate → 输入你新的URL地址 二:变更账号 TortoiseSVN右键->Setting 进入“Setting”之后,也就 ...

  9. 深入浅出 REST(转)

    文章讲的不错,更具体一些,对实践的指导意义更强 原文:https://www.infoq.cn/article/rest-introduction/ 不知你是否意识到,围绕着什么才是实现异构的应用到应 ...

  10. 我是如何一步步编码完成万仓网ERP系统的(六)产品库设计 2.百度Ueditor编辑器

    https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...