1

How can i make this code more compact considering i will have multiple values to assign and unassign

class A:
    def __init__(self,*args,**kwargs):
        self._a = 0
        self._b =0
    def set_a(self):
        self._a = 1
    def set_b(self):
        self._b = 1
    def unset_a(self):
        self._a =0
    def unset_b(self):
        self._b = 0

x=A()
x.set_a() 
print(x._a) # 1
x.unset_a()
print(x._a) # 0

i just want to avoid to write multiple set and unset function, just a simple 1 function where i pass the type (set/unset) and which varibale to target , that will do it

sahasrara62
  • 10,069
  • 3
  • 29
  • 44

2 Answers2

1

I'd be tempted to do something like the following, using a dictionary instead of multiple variables:

class A:
    def __init__(self,*args,**kwargs):
        self._d = {'_a': 0, '_b': 0}
    def set_d_item(self, key, val):
        self._d[key] = val

x=A()
x.set_d_item('_a', 1) 
print(x._d['_a']) # 1
x.set_d_item('_a', 0) 
print(x._d['_a']) # 0

If you really need the attributes as they are in your example, you could use exec(), but I wouldn't really recommend allowing arbitrary code execution:

class A:
    def __init__(self,*args,**kwargs):
        self._a = 0
        self._b =0
    def set_item(self, key, val):
        exec(f'self.{key} = {val}')

x=A()
x.set_item('_a', 1) 
print(x._a) # 1
x.set_item('_a', 0) 
print(x._a) # 0
CDJB
  • 14,043
  • 5
  • 29
  • 55
  • i also tried this way, this is conflicting with my other modules and i have to define the values as they are not in the dict, maybe some decorator which i am looking here – sahasrara62 Dec 04 '19 at 11:02
  • I've added a second option using `exec()`. – CDJB Dec 04 '19 at 11:06
  • exec is good way, but executing this and leaving it in my locals is is not what i require – sahasrara62 Dec 04 '19 at 11:11
  • I'm not sure what you mean by that - using exec will work just as your initial example worked. – CDJB Dec 04 '19 at 11:12
  • it i sbetter to avoid use of exec [see this for better explaination](https://stackoverflow.com/questions/1933451/why-should-exec-and-eval-be-avoided) – sahasrara62 Dec 04 '19 at 11:41
  • 1
    Absolutely - that's why I said I didn't recommend it. – CDJB Dec 04 '19 at 11:42
  • @CDJB you don't need to use `exec` to set an attribute for an object. You can use `setattr()` https://www.w3schools.com/python/ref_func_setattr.asp – Mikey Lockwood Dec 04 '19 at 11:48
1

You could use setattr based on a pre defined config to make it more compact

class A:
    _a = 0
    _b = 0

    var_config = {
        '_a': {'unset': 0, 'set': 1}, 
        '_b': {'unset': 0, 'set': 1}, 
    }

    def set_var(self, var, action='set'):
        setattr(self, var, self.var_config[var][action])


>>> x = A()
>>> print(x._a)
0

>>> x.set_var('_a') 
>>> print(x._a)
1

>>> x.set_var('_a', action='unset') 
>>> print(x._a)
0
Mikey Lockwood
  • 1,258
  • 1
  • 9
  • 22