Python 可变的 NamedTuple

Python mutable NamedTuple

我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有一些类型提示而不是不可变的。

所以我有这样的东西:

class ConnectionConfig(NamedTuple):
    name: str
    url: str
    port: int
    user: str = ""
    pwd: str = ""
    client: Any = None

但我想让它可变。我可以这样做:

class ConnectionConfig():
    def __init__(self, name: str, url: str, port: int, user: str = "", pwd: str = "", client: Any = None):
        self.name = name
        self.url = url
        self.port = port
        self.user = user
        self.pwd = pwd
        self.client = client

但是伙计...那太丑了:/ python 中是否有任何内置替代品? (使用 Python 3.6.3)

class ConnectionConfig():
    name: str
    url: str
    port: int
    user: str = ""
    pwd: str = ""
    client: Any = None
    def __init__(self, **kv):
        self.__dict__.update(kv)

然后你可以在构造函数中指定所有内容

c=ConnectionConfig(port=22)

print (c.port)  # will print 22

使用recordclass(pip install recordclass)怎么样?

from recordclass import recordclass


>>> Point = recordclass('Point', 'x y')

>>> p = Point(3, 2)
>>> p
Point(x=3, y=2)
>>> p.x = 8

它(几乎)与 namedtuple api 相同,而且它是可变的

实际上,您的实施是(唯一的)内置方式:

class ConnectionConfig():
    def __init__(self, name: str, url: str, port: int, user: str = "",
                 pwd: str = "", client: Any = None):
        pass

正在阅读 PEP 0484 I haven't found any other alternatives that fit your needs. Continuing the PEP chain, I guess this quote from PEP 20 The Zen of Python 解释:

There should be one-- and preferably only one --obvious way to do it.

在创建 NamedTuple 时调用“_asdict()”会将其转换为 OrderedDict(),但一点也不令人满意...

from typing import NamedTuple

class ConnectionConfig(NamedTuple):
    name: str
    url: str
    port: int
    user: str = ""
    pwd: str = ""

mutable_connection_cfg = ConnectionConfig("my_name", "my_url", 111, "my_user", "my_pwd")._asdict()

print(mutable_connection_cfg)
>> OrderedDict([('name', 'my_name'), ('url', 'my_url'), ('port', 111), ('user', 'my_user'), ('pwd', 'my_pwd')])

recordclass库的基础上有一个紧凑的解决方案:

> pip3 install recordclass

from recordclass import dataobject

class ConnectionConfig(dataobject):
    name: str
    url: str
    port: int
    user: str = ""
    pwd: str = ""
    client: Any = None

>>> con = ConnectionConfig('name','url',8080,'user','secret',tcp_client)

>>> sys.getsizeof(con)
108   # PyHEAD (16) + 6*sizeof(*void) bytes

如果想要更快地创建实例,有一个选项:

class ConnectionConfig(dataobject, fast_new=True):
    name: str
    url: str
    port: int
    user: str = ""
    pwd: str = ""
    client: Any = None

(注意:这个可能不太适合 IDE 编辑器的自动完成)

另一个选项:

>>> from recordclass import make_dataclass
>>> ConnectionConfig = make_dataclass(
          "ConnectionConfig",
          [('name',str), ('url',str), ('port',str), 
           ('use',str), ('pwd',str), ('client',Any)],
          defaults=(None,), 
          fast_new=True)