Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update a field in a dataclass with a field name known only during runtime

I'd like to update a field within a dataclass, but I know the field name only during runtime, not during development time.

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-

from dataclasses import dataclass # I use the backport to 3.6

@dataclass
class Template:
    number: int = 0
    name: str = "^NAME^"


oneInstance = Template()
print(oneInstance) # Template(number=0, name='^NAME^')
# If I know the variable name during development, I can do this:
oneInstance.number=77
# I get this from a file during runtime:
para = {'name': 'Jones'}
mykey = 'name'
# Therefore, I used exec:
ExpToEval = "oneInstance." + mykey + ' = "' + para[mykey] + '"'
print (ExpToEval) # oneInstance.name = "Jones"
exec(ExpToEval)  # How can I do this in a more pythonic (and secure) way?
print(oneInstance) # Template(number=77, name='Jones')

I need something like

oneInstance[mykey] = para[mykey]

but this ends up in "TypeError: 'Template' object does not support item assignment"

like image 919
JDi Avatar asked Mar 06 '23 08:03

JDi


2 Answers

You can try replace() method, like below:

from dataclasses import dataclass, replace

@dataclass
class Template:
    number: int = 0
    name: str = "^NAME^"

oneInstance = Template()
print(oneInstance)
para = {'name': 'Jones'}
oneInstance = replace(oneInstance, **para)
print(oneInstance)

That should do the job if your dict para only contains keys that are fields of your dataclass.

like image 54
Kirill Kalashnikov Avatar answered Mar 08 '23 08:03

Kirill Kalashnikov


You can use setattr to update an object's attributes during runtime:

oneInstance = Template()
setattr(oneInstance, 'name', 'Jones')  # this doesn't raise a TypeError
print(oneInstance.name)  # prints: 'Jones'
like image 33
Arne Avatar answered Mar 08 '23 08:03

Arne