python元类深入理解
1.python 中的类
在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象,python也为我们提供了手动创建类的方法,type()。type()这个方法对我们来说并不陌生,我们所熟知的用法是:class = type(instance),当传入一个参数时,type()返回这个参数的类。而今天我们要用到的是type的另一个功能。type("classname",(object,),{"name":"jiao"})。当给type传入三个参数时,就是一个手动创建类的方式。
class A():
def __init__(self,name):
self.name = name
print("创建了一个实例") a = type("a",(A,),{"name":"jiao"})
print(a) #<class '__main__.a'>
print(a.name) #jiao
print(a("jiang")) #创建了一个实例
#<__main__.a object at 0x00000280A973AA58>
type接收三个参数分别是:
classname: 要创建的class 的名称
object:要创建类的父类所组成的元组
sttr_dict: 要创建类的属性
type返回一个class,我们接收并赋值到一个变量上,现在这个变量就指向我们所创建的类,我们可以通过这个变量来使用类。
2.python 中的type
在python 中,几乎所有的东西都是对象,这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来——type
3.__metaclass__属性
python在创建类时,会按照如下的流程进行:
Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
那么在__metaclass__中放置什么样的代码可以创建类呢?type,或者任何使用到type或者子类化type的东东都可以。
4.自定义元类
class UpperAttrMetaClass(type):
def __new__(cls,class_name,class_parents,class_attr, *args, **kwargs):
print("__new__")
class_attr['name'] = "jiao"
return type.__new__(cls,class_name,class_parents,class_attr) def __init__(self,*args,**kwargs):
print("__init__")
super().__init__(*args, **kwargs)
self.__cache = {} def __call__(self, *args, **kwargs):
print("__call__")
if args in self.__cache:
return self.__cache[args]
else:
obj = super().__call__(*args)
self.__cache[args] = obj
return obj class A(metaclass=UpperAttrMetaClass):
def __init__(self,name):
self.name = name
print("a.__init__")
5.类的创建流程
1.元类的__new__(),返回创建好的类。当我们想要改变创建方式的时候就要重写这个方法。
2.元类的__init__(),初始化一些类的属性
6.实例创建流程
1.元类的__call__(),创建一个实例时,首先调用这个方法,返回创建好的实例,所以我们可以通过改写这个方法来改变实例创建过程,比如实现单例模式
2.类的__init__(),初始化实例属性
7.元类的应用
1.单例模式
class Singleton(type):
def __init__(cls,*args,**kwargs):
cls.__instance = None
super().__init__(*args,**kwargs) def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args,**kwargs)
return cls.__instance
else:
return cls.__instance class Spam(metaclass=Singleton):
def __init__(self):
print("Creating Spam")
2.缓存模式
import weakref class Cached(type):
def __init__(cls,*args,**kwargs):
super().__init__(*args,**kwargs)
cls.__cache = weakref.WeakValueDictionary() def __call__(cls, *args, **kwargs):
if args in cls.__cache:
return cls.__cache[args]
else:
obj = super().__call__(*args)
cls.__cache[args] = obj
return obj class Spams(metaclass=Cached):
def __init__(self,name):
print("Creating Spam({!r})".format(name))
self.name = name
3.获取属性的定义顺序
能过获取到属性的定义顺序,我们就可以通过简单的方法实现属性到数据的映射,可以更加简单的将类中的属性数据化。
from collections import OrderedDict class Typed:
_excepted_type = type(None) def __init__(self,name=None):
self._name = name def __set__(self, instance, value):
if not isinstance(value,self._excepted_type):
raise TypeError("Excepted"+str(self._excepted_type))
instance.__dict__[self._name] = value class Integer(Typed):
_excepted_type = int class Float(Typed):
_excepted_type = float class String(Typed):
_excepted_type = str class OrderedMeta(type): def __new__(cls, clsname,bases,clsdict):
d = dict(clsdict)
order = []
for name,value in clsdict.items():
if isinstance(value,Typed):
value._name = name
order.append(name)
d['_order'] = order
return type.__new__(cls,clsname,bases,d) @classmethod
def __prepare__(metacls, name, bases):
return OrderedDict() #注:__prepare__该方法会在类定义一开始的时候调用,调用时以类名和基类名称作为参数,它必须返回一个映射对象,供处理类定义体时调用 #eg.
class Structure(metaclass=OrderedMeta): def as_csv(self):
return ','.join(str(getattr(self,name)) for name in self._order) class Stock(metaclass=OrderedMeta):
name = String()
shares = Integer()
price = Float()
def __init__(self,name,shares,price):
self.name = name
self.shares = shares
self.price = price s = Stock("haha",23,23.3)
print(s.name)
s = Stock(34,23,34)
# print(s.as_csv())
8.小结
元类主要就是在类和实例创建的时候发挥作用,来实现一些功能。
python元类深入理解的更多相关文章
- Python进阶丨如何创建你的第一个Python元类?
摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...
- python元类:type和metaclass
python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...
- Python 元类 - Metaclasses
Python 元类 - Metaclasses 默认情况下儿, classes 是有 type() 构造的. 类的结构体在一个新的 namespace 被执行, 类的名字 class name 绑定( ...
- python元类理解2
恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...
- python 元类理解
原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...
- 深入理解python元类
类也是对象 在理解元类之前,你需要先掌握Python中的类.Python 中的类概念借鉴 Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.当然在 P ...
- 对python中元类的理解
1. 类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍然成立: >>> class ObjectCreator(object): ...
- Python元类__prepare__方法深入理解
学习元类的时候,对__prepare__不是很理解,书上讲解的也不是很详细,最后通过查看stackoverflow的一些帖子对该方法有了一些理解,记录如下: 先看代码: class member_ta ...
- 深入理解 python 元类
一.什么的元类 # 思考: # Python 中对象是由实例化类得来的,那么类又是怎么得到的呢? # 疑问: # python 中一切皆对象,那么类是否也是对象?如果是,那么它又是那个类实例化而来的呢 ...
随机推荐
- HTML连载16-颜色控制属性2&标签选择器
一.颜色控制属性(上接连载15) (4)十六进制 在前端开发中通过十六进制来表示颜色,其实本质就是RGB,十六进制中是通过每两位表示一个颜色. 例如:#FFEE00,其中FF代表的是R,EE代表的G, ...
- Libra 加密稳定币:Facebook的"野心"?
2008年11月1日,有一个传说叫中本聪的日裔美国人,发表了一篇名为<比特币:一种点对点式的电子现金系统>的论文.2009年,比特币出世,从此开启了电子货币这个收割机器,全世界的韭菜都是一 ...
- Spring Boot:整合MyBatis框架
综合概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单 ...
- vscode+vagrant+xdebug调试
配置: { "name": "Listen for XDebug", "type": "php", "requ ...
- redis安装与php安装redis模块
一.安装redis 1.下载 wget https://github.com/antirez/redis/archive/2.8.23.tar.gz 2.解压缩 tar -zxvf 2.8.23.ta ...
- mybatis以及预编译如何防止SQL注入
SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者).[摘自] SQL injection - Wikipedia SQL ...
- Django迁移数据库报错
Django迁移数据库报错 table "xxx" already exists错误 django在migrate时报错django migrate error: table 'x ...
- python爬取拉勾网数据并进行数据可视化
爬取拉勾网关于python职位相关的数据信息,并将爬取的数据已csv各式存入文件,然后对csv文件相关字段的数据进行清洗,并对数据可视化展示,包括柱状图展示.直方图展示.词云展示等并根据可视化的数据做 ...
- 如何配置selinux
参考命令: 一.开启/关闭selinux getenforce:查看selinux运行状态 setenforce 0 :关闭selinux setenforce 1 :开启selinux 系统 ...
- 高性能微服务网关.NETCore客户端Kong.Net开源发布
前言 项目地址:https://github.com/lianggx/Kong.Net 你的支持使我们更加强大,请单击 star 让更多的 .NETCore 认识它. 拥抱开源的脚步,我们从来都是一直 ...