securisec
securisec

Reputation: 4041

How can i define an object of arrays using attrs?

Consider the following data set:

{
    'name': 'somecat',
    'lives': [
        {'number': 1, 'did': 'nothing'},
        {'number': 2, 'did': 'saved the world'}
    ]
}

What I am trying to do is use attrs to define a dataclass so that I can get autocompletion even when using an index number

import attr

@attr.s
class Cat(object):
    name = attr.ib()
    lives: list = [
        {'number': int, 'did': str} # trying to get autocompletion here
    ]


c = Cat('somecat')
print(c)
c.lives[0].number # trying to get autocompletion here

The above code is not valid, but this is what I am trying to accomplish.

How can I go about doing this? I am aware of metadata, but that is immutable. I am open to using dataclasses also if that makes more sense.

Upvotes: 0

Views: 318

Answers (1)

Buckeye14Guy
Buckeye14Guy

Reputation: 851

Admittedly I never really use the attr module but in order to make minimal changes to your code. I think using typing.List is also useful here. I personally would've used dataclasses but this seems to work as well

import attr
import typing
from collections import namedtuple

live = namedtuple('live', ['number', 'did'])


@attr.s
class Cat(object):
    name = attr.ib()
    lives: typing.List[live] = attr.ib()


c = Cat('somecat', lives=[live(**{'number': 1, 'did': 'smile'})])
print(c)
c.lives[0].number  # auto completes

With just dataclasses

import typing
from dataclasses import dataclass


@dataclass
class live:
    number: int
    did: str


@dataclass
class Cat:
    name: str
    lives: typing.List[live]


c = Cat('somecat', lives=[live(**{'number': 1, 'did': 'smile'})])
print(c)
c.lives[0].number  # autocompletes

But for nested dictionaries, these dataclasses can be tough. Like so

data = {
    'name': 'somecat',
    'lives': [
        {'number': 1, 'did': 'nothing'},
        {'number': 2, 'did': 'saved the world'}
    ]
}

new_c = Cat(**data)
new_c.lives = [live(**data) for data in new_c.lives]

If I may, I would suggest looking into pydantic.

Thanks

Upvotes: 1

Related Questions