大家可能很熟悉在collections模块中有一个很好用的扩展数据类型-namedtuple。

如果你还不知道这个类型,那么请翻看标准手册。

我利用元类轻松定义一个namedtuple。

先把代码贴上,满足心急的朋友。

def myNamedTuple(tuple_name, attrs_str):
attrs_set = set(attrs_str.split(' '))
def __init__(self, attrs): #我们将来实例初始化的时候需要调用的方法。
for key, value in zip(attrs_set, set(attrs)):
self.__dict__[key]=value
def __str__(self): #这个只是方便打印用的。
values = [str(x) for x in self.__dict__.values()]
return tuple_name+'(' + ', '.join(values) + ')'
def to_dict(self): #提供一个to_dict()方法,用来把我们的命名元组转为字典。
return self.__dict__
#调用type来建立类。
#第二个参数指定其继承自元组。
#第三个参数指定我们需要存入的属性名(也就是__dict__的键名,然后就是上面定义的方法。
return type(tuple_name, (tuple,),{'attr_keys':attrs_set,'__init__':__init__,'__str__':__str__,'to_dict':to_dict}) if __name__=='__main__':
Point = myNamedTuple('Point','x y')
p = Point([1,2]) #目前我们的参数只能传入一个,否则报错,这是和namedtuple之间的差别。
print(p)
print(type(Point),p, sep='\n')
print(p.x,'---',p.y)
print(p[0],p[1])
print(p.to_dict)
p +=(4,) #此时已经变成了普通的tuple了。内置的namedtuple也是一样。
print(type(Point),p, sep='\n')

实现方法

其实,Python的内部也是创建了一个继承自tuple的类。

>>> from collections import namedtuple
>>> Rectangle=namedtuple('Rectangle', 'height width')
>>> r = Rectangle(3,4)
>>> type(r)
<class '__main__.Rectangle'>

建立一个列表用来存储所有需要存入的健。在将来实例化调用__init__方法的时候,我们再来建立实例的__dict__属性字典。

至于取值,那么就是类调用实例的__dict__了。

如果看不明白的,请先看我关于元类介绍的那一讲。

改进

由于我们的类继承自元组,而元组默认只能传入一个可迭代对象。

那么我们修改一下原来的代码,让我们的myNamedTuple也可以像namedtuple一样可以接受多个参数。


def myNamedTuple(tuple_name, attrs_str):
class Meta(type): #定义一个元类,采用`__call__`方法来拦截类的实例化,在实例化之前我们先把位置参数全部转入一个叫args的元组中,然后在调用type的`__call__`方法,从而把刚才的元组传进去,这样就只有一个参数了,从而无论你传入多少个位置参数,在这个步骤之后,只会出现一个参数了,成功!
def __call__(self, *args):
return type.__call__(self, args)
attrs_set = set(attrs_str.split(' '))
def __init__(self, args):
for key, value in zip(attrs_set, set(args)):
self.__dict__[key]=value
def __str__(self):
values = [str(x) for x in self.__dict__.values()]
return tuple_name+'(' + ', '.join(values) + ')'
def to_dict(self):
return self.__dict__
return Meta(tuple_name, (tuple,),{'attr_keys':attrs_set,'__init__':__init__,'__str__':__str__,'to_dict':to_dict}) if __name__=='__main__':
Point = myNamedTuple('Point','x y')
print(Point)
p = Point(1,2) #多个参数成功调用....
print(p)
print(type(Point),p, sep='\n')
print(p.x,'---',p.y)
print(p[0],p[1])
print(p.to_dict)
p +=(4,) #此时已经变成了普通的tuple了。
print(type(Point),p, sep='\n')

如果有什么不懂的,请留言。

如果这个例子通了,那么collections中的其他数据类型是不是也是一样的道理呢?

Python元类实践--自己定义一个和collections中一样的namedtuple的更多相关文章

  1. Python 元类使用讲解

    我要一大群的类都具有一种特点,我怎么给他们加上呢?模板嘛,我从这个模板创建一群类不就OK了?那就需要元类了. 定义一个元类(就是一个类的模板!莫多想,还要记住这是类级别的,不是对象级别的!):代码如下 ...

  2. Python进阶丨如何创建你的第一个Python元类?

    摘要:通过本文,将深入讨论Python元类,其属性,如何以及何时在Python中使用元类. Python元类设置类的行为和规则.元类有助于修改类的实例,并且相当复杂,是Python编程的高级功能之一. ...

  3. python元类理解2

    恩,对元类理解又有新的收获,其实类似于装饰器,只不过装饰器是修饰函数,元类用来定制一个类. 代码如下,这是一个使用了函数做元类传递给类: input: def upper_attr(class_nam ...

  4. python元类:type和metaclass

    python元类:type和metaclass python中一切皆对象,所以类本身也是对象.类有创建对象的能力,那谁来创建类的呢?答案是type. 1.用tpye函数创建一个类 class A(ob ...

  5. python元类深入理解

    1.python 中的类 在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象, ...

  6. [TimLinux] Python 元类

    1. type函数 name = "This is a string" print(type(name)) # <class 'str'> print("*& ...

  7. python 元类理解

    原文来自:https://segmentfault.com/a/1190000011447445 学懂元类,你只需要知道两句话: 道生一,一生二,二生三,三生万物 我是谁?我从哪来里?我要到哪里去? ...

  8. Python元类之由浅入深

    前言 ​ 元类属于python面向对象编程的深层次的魔法,非常重要,它使我们可以更好的掌控类从创建到消亡的整个生命周期过程.很多框架的源码中都使用到了元类.例如 Django Framework 中的 ...

  9. Python 元类的基本介绍及使用

    一.什么是元类 二.如何使用元类 (一)不依赖class关键字创建一个自定义类 (二)自定义元类控制类的产生 (三)自定义元类控制类的调用 一.什么是元类 在python中,一切皆对象,而对象都是由类 ...

随机推荐

  1. Android_CntextMenu_example_textSize

    menu.xml <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item ...

  2. gradle与maven项目相互转化

    gradle这几年发展迅猛,github越来越多的项目都开始采用gradle来构建了,但是并不是所有人都对gradle很熟悉,下面的方法可以把gradle转成maven项目,前提gradle项目目录结 ...

  3. nodejs使用express4框架默认app.js配置说明

    var express = require('express'); //引入express模块 var path = require('path'); //引入path模块,该模块包括了一些处理文件路 ...

  4. [原] Unity下的ElectroServer的连接

    ES的版本是5.4.1,示例目录下code_examples\ConnectAndLoginManually是Unity的连接和登录代码. 除了host和port需要指定,在连接时需要指定连接方式,如 ...

  5. js如何实现一定时间后去执行一个函数

    js如何实现一定时间后去执行一个函数:在实际需要中可能需要规定在指定的时间之后再去执行一个函数以达成期望的目的,这也就是一个定时器效果,恰好在js中就已经给定了这样的一个函数setTimeout(), ...

  6. JavaScript 零散知识点1 (正则表达式+定时器+hover)

    1.clear:both清楚浮动影响//css中 2.正则表达式 search方法 :指明是否存在相应的匹配,如找到一个返回一个整数值,表明这个匹配距离字符串开始的偏移位置,如果没有找到匹配返回-1f ...

  7. asp下实现多条件模糊查询SQL语句

    常写一个简单的模糊查询的SQL语句格式可以如下例: sql="select * from 表名 where 字段名 like ’%" & request.form(&quo ...

  8. linux+asp.net core+nginx+sql server

    Linux Disibutaion:Ubuntu 16.04.1 LTS Web Server:Nginx.Kestrel 安装.net core sudo sh -c 'echo "deb ...

  9. ### core文件使用

    在Linux下程序崩溃,特别是在循环中产生Segment Fault错误时,根本不知道程序在哪出错,这时,利用core文件可以快速找到出错的问题所在. #@author: gr #@date: 201 ...

  10. 基于游标的定位DELETE/UPDATE语句

    如果游标是可更新的(也就是说,在定义游标语句中不包括Read Only 参数),就可以用游标从游标数据的源表中DELETE/UPDATE行,即DELETE/UPDATE基于游标指针的当前位置的操作: ...