Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 有没有办法将工厂函数赋予`typing.NamedTuple`子类?_Python 3.x_Python Typing - Fatal编程技术网

Python 3.x 有没有办法将工厂函数赋予`typing.NamedTuple`子类?

Python 3.x 有没有办法将工厂函数赋予`typing.NamedTuple`子类?,python-3.x,python-typing,Python 3.x,Python Typing,注意:我已经用Python3.6.7实现了这一点,但是那里的NamedTuple文档没有更改,所以我怀疑它是否会在那里更改 因此,我正在查看类型包中的类,我想知道是否有一种方法可以向其添加可变的默认值。第一次尝试是看我是否可以使用\u makeclassmethod来发挥我的优势,但是后来我发现该类检查了覆盖\u new\u (重述:如果将[]放入默认值,则每个对象都会共享相同的列表。对于旧的集合.namedtuple和新的键入.namedtuple,这就是集合.defaultdict类在构造函

注意:我已经用Python3.6.7实现了这一点,但是那里的
NamedTuple
文档没有更改,所以我怀疑它是否会在那里更改

因此,我正在查看类型包中的类,我想知道是否有一种方法可以向其添加可变的默认值。第一次尝试是看我是否可以使用
\u make
classmethod来发挥我的优势,但是后来我发现该类检查了覆盖
\u new\u

(重述:如果将
[]
放入默认值,则每个对象都会共享相同的列表。对于旧的
集合.namedtuple
和新的
键入.namedtuple
,这就是
集合.defaultdict
类在构造函数中具有
默认工厂
参数的原因。)

>>通过键入import NamedTuple,List
>>>班级人员(姓名为两人):
...   姓名:str
...   儿童:名单[“人”]
...   定义新(自我,姓名:str,子女:列表['Person']=None):
...     返回人。\u make(姓名,如果子女不是其他人,则为子女[])
... 
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib/python3.6/typing.py”,第2163行,新__
raise AttributeError(“无法覆盖NamedTuple属性”+键)
AttributeError:无法覆盖NamedTuple属性\uu新建__
>>>
我一直在琢磨如何在顽固的
\uuuuuu new\uuuuuuu
中隐藏一个列表,但随后它开始变得毫无意义

>>> class Person(NamedTuple):
...   name: str
...   children: List['Person'] = None
... 
>>> 
>>> def new_new(name: str, children: List[Person] = None) -> Person:
...   return Person(name, [] if children is None else children)
... 
>>> old_new = Person.__new__
>>> def new_new(name: str, children: List[Person] = None) -> Person:
...   return old_new(name, [] if children is None else children)
... 
>>> Person.__new__ = new_new
>>> 
>>> Person('John')
Person(name='John', children=None)
>>> Person.__new__
<function new_new at 0x7f776b2b2e18>
>>> new_new('John')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in new_new
  File "<string>", line 14, in __new__
TypeError: tuple.__new__(X): X is not a type object (str)
>>> new_new(Person, 'John')
Person(name='John', children=None)
>>> 

NamedTuple
仅提供类型检查的NamedTuple。
命名为tupleMeta
覆盖
\uuuuuuu新的
\uuuuuuuuu初始化
和其他一些。你唯一的机会就是改变
命名双工的工作方式


防止覆盖的保护本身不受保护。这允许您以各种方式对其进行修补


您可以从受保护的名称中删除
\uuuu new\uuu

import typing
typing._prohibited = typing._prohibited[1:]
这允许您直接覆盖类中的
\uuuu new\uuu
。 请注意,这将影响所有
NamedTuple
子类型


您可以派生一个不保护
\uuuu new\uuuu
的新元类,并将其用于您的
NamedTuple
实例:

class NamedTupleUnprotectedMeta(typing.NamedTupleMeta):
    def __new__(cls, typename, bases, ns):
        ...
        # copy verbatim from NamedTupleMeta
        ...
        # update from user namespace without protection
        for key in ns:
            if key not in typing._special and key not in nm_tpl._fields:
                setattr(nm_tpl, key, ns[key])
        return nm_tpl


class Person(NamedTuple, metaclass=NamedTupleUnprotectedMeta):
    ...
这允许您直接覆盖类中的
\uuuu new\uuu
,而不影响
NamedTuple
的其他子类型。请注意,还可以让元类添加一个自定义的
new
,以调用类主体中设置的默认值


请注意,
NamedTupleMeta
也会忽略
base
,因此也不能使用mixin等。任何广泛的更改都需要先重写
NamedTupleMeta


如果您只需要具有默认值的存储类,则和提供与您描述的内容匹配的声明:

@attr.s(auto_attribs=True)
class Person:
    name: str
    children: List['Person'] = attr.Factory(list)

这两个包都支持冻结,这类似于元组的不变性。

虽然它不能严格回答您的问题,但支持类型检查和所需的默认参数工厂。不过,它不会创建一个NamedTuple。这可能是我将仔细研究的内容,然后尝试在任何地方使用,但正如你所说的,不是这个问题的答案。虽然,“它不是为了强大”也是一个完全正确的答案。请注意,
人的行为是一致的。调用
Person(*args)
相当于
Person.\uuu new\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(Person,*args)
,而不是
Person.\u<代码>\uuuuuuuuuuuuuuuuuuuuuuuu
被默认元类
type
调用,就像调用
类方法一样。
@attr.s(auto_attribs=True)
class Person:
    name: str
    children: List['Person'] = attr.Factory(list)