Search code examples
pythonnamedtuple

NamedTuple is shared across variables


from typing import NamedTuple, List, Set, Tuple, Dict

class EmbeddingInfoStruct(NamedTuple):
    emb_names : list[str] =[]
    idx_in_data: list[int] =[]
    emb_dim: list[int] =[]

info1 =EmbeddingInfoStruct()
info1.emb_names.append("name1")

info2=EmbeddingInfoStruct()

print("info1 address = ", id(info1), ", info2 address = " ,id(info2))
print (info1)
print (info2)

output of print :

info1 address =  2547212397920 , info2 address =  2547211152576
EmbeddingInfoStruct(emb_names=['name1'], idx_in_data=[], emb_dim=[])
EmbeddingInfoStruct(emb_names=['name1'], idx_in_data=[], emb_dim=[])

Surprisingly info1 and info2 both share the same value. I'd expect info2.emb_names to be empty. Why does NamedTuple behaves like it's a "static class"?


Solution

  • I think you mistook NamedTuple from the typing module, describing the type of a named tuple for type hinting purpose, and the named tuple you can get from namedtuple() from the collection package (see the collection documentation).

    Here, you are actually changing class member of your EmbeddingInfoStruct, thus the "static class" behavior.


    Using this, your class declaration would rather look like

    from collections import namedtuple
    EmbeddingInfoStruct = namedtuple("EmbeddingInfoStruct",["emb_names", "idx_in_data", "emb_dim"],defaults=[list(),list(),list()])
    
    info1 = EmbeddingInfoStruct()
    

    You will, however, probably fall into the pitfall of "mutable" as default arguments, as explained there