4

I am looking for a struct like data structure I can create multiple instances from and have some type hinting without being immutable.

So I have something like this:

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

But I would like to have it mutable. I could do it like that:

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

But man... that is ugly :/ Are there any built-in alternatives in python? (using Python 3.6.3)

3
  • Can you use *args and **kwargs? Commented Oct 21, 2017 at 17:19
  • but then I can't use type hinting anymore right? Commented Oct 21, 2017 at 17:23
  • You could use **kwargs and a (for) loop. And you could use eval (or exec) for this one. I'm just not sure about this because every time I use eval for assigning variables it throws an error. Commented Oct 21, 2017 at 18:08

6 Answers 6

3

Your implementation is quite the (only) built-in way to do it, actually:

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

Reading 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 explains it:

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

Sign up to request clarification or add additional context in comments.

Comments

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

then you can specify everything in the constructor

c=ConnectionConfig(port=22)

print (c.port)  # will print 22

2 Comments

I actually already tried that one before. But the type hints are not working that way. I maybe didn't specify that in my question good enough.
The type hints will not work because they are not in the init
1

There is a compact solution on the base of recordclass library:

> 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

If one want faster instance creation there is an option:

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

(Note: that this one could be less comfortable with IDE editor's autocompletion)

Another option:

>>> 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)

Comments

0

How about using 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

It's (nearly) the same api as namedtuple and it's mutable

4 Comments

I would prefer sth built in. Nevertheless, I also don't see how type hinting can be used.
Are you sure this doesn't work with your IDE? ipython knows to autocomplete with recordclass
I never said it does not work. But again, how can I use type hints with recordclass. As I see it, that does not work.
Jodo: recordclass already support typehints:: from recordclass import RecordClass from typing import Any class 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
0

Calling "_asdict()" on creation of the NamedTuple will transform it to an OrderedDict(), but not really satisfying at all...

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')])

Comments

0

You can use the pass statement.

class myclass: pass

Then you can create the attributes just before using them:

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

1 Comment

If you're going this route, a cleaner way is to use SimpleNamespace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.