Pythonic way to delete variable from self if it exists in a list
Asked Answered
A

6

8

I have a list of strings ['foo1', 'foo2', ...] that represent variables that I want to delete from self if they are part of self. What is a Pythonic and compact way to do this?

My first attempt is

if hasattr(self, 'foo1'):
    del self.foo1
if hasattr(self, 'foo2'):
    del self.foo2
...

but this obviously isn't scalable for a large list.

Can anyone help?

Alanson answered 17/2, 2017 at 17:6 Comment(3)
Why do you want to do this?Decoder
Possible duplicate of Python - how can I dynamically remove a method from a class -- i.e. opposite of setattrEntablement
@Decoder I have a class that can be modified after it is initialized (initialization is computationally expensive). There are certain rules on how it can be modified. My motivation behind deleting from self was to destroy variables/objects in the class if the class is modified incorrectly and these variables/objects are no longer valid. Perhaps, I should split the class into parent and child.Alanson
S
17

You can use a for loop and at the same time boost performance by using pop on the __dict__ of the object:

for attr in ('foo1','foo2'):
    self.__dict__.pop(attr,None)

pop basically does a check whether the element is in the dictionary and removes it if that is the case (it also returns the corresponding value, but that is not relevant here). We also use None here as a "default" return value such that if the key does not exists, pop will not error.

Suttle answered 17/2, 2017 at 17:11 Comment(1)
I didn't realize dicts also had a pop method.Decoder
E
15

You can use delattr. It will raise an AttributeError if the attribute does not exist, so you can wrap it in a method if you want:

def safe_delattr(self, attrname):
    if hasattr(self, attrname):
        delattr(self, attrname)

or use a try/except block:

try:
    delattr(self, attrname)
except AttributeError:
    pass

This has the advantage of working with classes that define __slots__, as they don't expose a __dict__ attribute.

Entablement answered 17/2, 2017 at 17:12 Comment(1)
Or try: ...; except AttributeError: ... for EAFP.Arnoldarnoldo
S
2

There is delattr(), although I can't think of many cases where deleting an attribute of an object is useful.

Schmaltzy answered 17/2, 2017 at 17:10 Comment(0)
B
2

something like this perhaps?

def del_attr(self, list):
    for l in list:
        delattr(self, l)
Brewster answered 17/2, 2017 at 17:13 Comment(0)
B
2

You can do this quite easily, but I have to say it seems at first glance like a pretty bizarre requirement. Generally in Python anything that involves dynamic creation and/or deletion of variables is a code smell, so I'd be interested in how the requirement emerged (and whether your description might not be obscuring the real problem).

But remembering that instance variables are stored in self.__dict__, and assuming that your list of strings is called los you can do what you want with something like this

for s in los:
    if s in self.__dict__:
        del self.__dict__[s]
Butterfly answered 17/2, 2017 at 17:14 Comment(1)
Note that WillemVanOlson's solution using pop() is superiorButterfly
B
1

Run it in a loop?

var_names = ["foo1", "foo2", "foo3"]
for var_name in var_names:
    delattr(self, var_name)
Blizzard answered 17/2, 2017 at 17:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.