python – 让namedtuple接受kwargs

如果我有一个类:
class Person(object):
    def __init__(self,name,**kwargs):
        self.name = name

p = Person(name='joe',age=25) # age is ignored

额外的参数被忽略了.但如果我有一个namedtuple,我会得到`意外的关键字参数

from collections import namedtuple 

Person = namedtuple('Person','name')
p = Person(name='joe',age=25)

# Traceback (most recent call last):
#   File "python",line 1,in <module>
# TypeError: __new__() got an unexpected keyword argument 'age'

我如何让namedtuple接受kwargs,这样我才能安全地传递额外的参数?

解决方法

解释器中的以下会话显示解决问题的一种可能解决方案:
Python 3.5.0 (v3.5.0:374f501f4567,Sep 13 2015,02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright","credits" or "license()" for more information.
>>> import collections
>>> class Person(collections.namedtuple('base','name')):
    __slots__ = ()
    def __new__(cls,*args,**kwargs):
        for key in tuple(kwargs):
            if key not in cls._fields:
                del kwargs[key]
        return super().__new__(cls,**kwargs)


>>> p = Person(name='joe',age=25)
>>> p
Person(name='joe')
>>>

替代方案:

由于您更倾向于使用更简单的解决方案,因此您可能会发现下一个程序更符合您的喜好:

#! /usr/bin/env python3
import collections


def main():
    Person = namedtuple('Person','name')
    p = Person(name='joe',age=25)
    print(p)


def namedtuple(typename,field_names,verbose=False,rename=False):
    base = collections.namedtuple('Base',verbose,rename)
    return type(typename,(base,),{
        '__slots__': (),'__new__': lambda cls,**kwargs: base.__new__(cls,**{
            key: value for key,value in kwargs.items()
            if key in base._fields})})


if __name__ == '__main__':
    main()

相关文章

我最近重新拾起了计算机视觉,借助Python的opencv还有face_r...
说到Pooling,相信学习过CNN的朋友们都不会感到陌生。Poolin...
记得大一学Python的时候,有一个题目是判断一个数是否是复数...
文章目录 3 直方图Histogramplot1. 基本直方图的绘制 Basic ...
文章目录 5 小提琴图Violinplot1. 基础小提琴图绘制 Basic v...
文章目录 4 核密度图Densityplot1. 基础核密度图绘制 Basic ...