创建具有附加功能的自定义namedtuple类型 [英] create custom namedtuple type with extra features

查看:117
本文介绍了创建具有附加功能的自定义namedtuple类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建自己的具有某些附加功能的内置namedtuple类型.假设我们创建了一个类:

I'd like to create my own type of build-in namedtuple that has some extra features. Let's say we create a class:

from collections import namedtuple
MyClass = namedtuple('MyClass', 'field1 field2')

它是一成不变的,易读的和简单的.现在,我可以创建MyClass的实例:

It`s immutable, readable and simple. Now I can create instances of MyClass:

myobj = MyClass(field1 = 1, field2 = 3.0)
print(myobj.field1, myobj.field2)

我的额外要求是创建实例时,我想检查field1是否为int类型以及field2是否为float.例如,如果用户尝试创建MyClass实例:

My extra requirement is when instance is created I'd like to check if field1 is int type and field2 is float. For example if user try to create MyClass instance:

obj = MyClass(field1 = 1, field2 = 3.0) # instantiates ok
obj1 = MyClass(field1 = 'sometext', field2 = 3.0) # raises TypeError

我试图制作一个自定义的namedtuple,它可以验证类似以下数据类型(MyClass应该是不可变的):

I tried to make a customized namedtuple that can validate datatypes (MyClass should be immutable) something like.:

MyClass = modifiednamedtuple('MyClass', 'field1 field2', (int, float) )

但被卡住了:(.namedtuple是函数(不能是ModifyedNamedtuple的基类),我对元类的实验失败了.

but got stuck :(. namedtuple is function (cannot be a baseclass for modifiednamedtuple), my experiments with metaclasses failed.

有任何提示或建议吗?

好的,我想出了一个可能不是干净"或pythonic的解决方案.除了我的对象不是不可变的以外,它都可以工作.如何使它们不变?有什么建议可以使它更干净,更可重用吗?

ok, I came up with a solution that might be not "clean" or pythonic. It works except that my objects are not immutable. How to make them immutable? Any suggestions how to make it more clean and redable?

这是我的代码.

def typespecificnamedtuple(name, *attr_definitions):

    def init(self, *args, **kwargs):
        valid_types = dict(attr_definitions) # tuples2dict
        for attr_name, value in kwargs.items():
            valid_type = valid_types[attr_name]
            if not isinstance(value, valid_type):
                raise TypeError('Cannot instantiate class '+ self.__name__+
                    '. Inproper datatype for '+ attr_name + '=' + str(value)+ 
                        ', expected '+str(valid_type) )
            setattr(self, attr_name, value)


    class_dict = {'__init__' : init, '__name__' : name}
    for attr_def in attr_definitions:
        class_dict[attr_def[0]] = attr_def[1] # attr_def is ('name', <type int>)

    customType = type(name, (object, ), class_dict )
    return customType

if __name__ == '__main__':
    MyClass = typespecificnamedtuple('MyClass', ('value', int), ('value2', float)  )
    mc = MyClass(value = 1, value2 = 3.0)
    mc.something = 1    # this assigment is possible :( how to make immutable?
    print(mc.__name__, mc.value, mc.value2, mc.something)
    mc1 = MyClass(value = 1, value2 = 'sometext')   # TypeError exception is raised

和控制台输出.:

MyClass 1 3.0 1
Traceback (most recent call last):
  File "/home/pawel/workspace/prices/prices.py", line 89, in <module>
    mc1 = MyClass(value = 1, value2 = 'sometext')   # TypeError exception is raised
  File "/home/pawel/workspace/prices/prices.py", line 70, in init
    ', expected '+str(valid_type) )
TypeError: Cannot instantiate class MyClass. Inproper datatype for value2=sometext, expected <class 'float'>

您注意到,

推荐答案

namedtuple不是课程;这是一个功能.但这是一个返回类的函数.因此,您可以将namedtuple调用的结果用作父类.

namedtuple isn't a class, as you note; it's a function. But it's a function that returns a class. Thus, you can use the result of the namedtuple call as a parent class.

由于它是不可变的,因此在__new__中而不是在__init__中初始化namedtuple.

Since it is immutable, a namedtuple is initialized in __new__ rather in in __init__.

也许是这样的:

MyTuple = namedtuple('MyTuple', 'field1 field2')

class MyClass(MyTuple):
    def __new__(cls, field1, field2):
        if not isinstance(field1, int):
            raise TypeError("field1 must be integer")
        # accept int or float for field2 and convert int to float
        if not isinstance(field1, (int, float)):
            raise TypeError("field2 must be float")
        return MyTuple.__new__(cls, field1, float(field2))

这篇关于创建具有附加功能的自定义namedtuple类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆