Python 可变 NamedTuple

Python mutable NamedTuple

提问人:Jodo 提问时间:10/22/2017 最后编辑:Jodo 更新时间:8/26/2022 访问量:2566

问:

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

所以我有这样的东西:

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)

结构 蟒蛇-3.6 可变 namedtuple

评论

0赞 Bryan Zeng 10/22/2017
你能用和吗?*args**kwargs
0赞 Jodo 10/22/2017
但是我不能再使用类型提示了,对吧?
0赞 Bryan Zeng 10/22/2017
您可以使用 和 () 循环。你可以用(或)来做这个。我只是不确定这一点,因为每次我使用 eval 分配变量时,它都会抛出一个错误。**kwargsforevalexec

答:

2赞 gambuzzi 10/22/2017 #1
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

评论

0赞 Jodo 10/22/2017
实际上,我之前已经尝试过了。但是类型提示不是这样工作的。我可能没有在我的问题中说明这一点。
1赞 viddik13 10/27/2017
类型提示将不起作用,因为它们不在初始化
0赞 maor10 10/22/2017 #2

使用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 相同,并且是可变的

评论

0赞 Jodo 10/22/2017
我更喜欢内置的。不过,我也不明白如何使用类型提示。
0赞 maor10 10/22/2017
您确定这不适用于您的 IDE 吗?ipython 知道使用 recordclass 自动完成
0赞 Jodo 10/22/2017
我从来没有说过它不起作用。但同样,我如何在 recordclass 中使用类型提示。在我看来,这是行不通的。
0赞 intellimath 9/30/2018
Jodo:已经支持 typehints:: from recordclass import RecordClass from typing import 任何类 ConnectionConfig(RecordClass): name: str url: str port: int user: str = “” pwd: str = “” client: Any = None >>> cf = ConnectionConfig('name', 'example.com', 8080, 'qwerty', None) >>> print(cf.name, cf.url, cf.port, cf.pwd, repr(cf.client)) name example.com 8080 None None Nonerecordclass
3赞 viddik13 10/27/2017 #3

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

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

阅读 PEP 0484 我还没有找到任何其他适合您需求的替代方案。继续 PEP 链,我想 PEP 20 The Zen of Python 中的这句话解释了这一点:

应该有一种——最好只有一种——显而易见的方法。

0赞 Jodo 10/28/2017 #4

在创建 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')])
1赞 intellimath 8/1/2021 #5

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)
0赞 David 8/26/2022 #6

您可以使用该语句。pass

class myclass: pass

然后,您可以在使用属性之前创建属性:

myclass.a=0
myclass.b='string'

评论

0赞 Keith 1/23/2023
如果要走这条路,更简洁的方法是使用 SimpleNamespace