Which is smarter?

class HoldAttr(object): pass
a = HoldAttr

b = getattr(a, 'attrname', [])
b.append(1)
setattr(a, 'attrname', b)

# or

try:
    b.a.append(1)
except AttributeError:
    b.a = [1]

... or something else?

Trying to learn.

Recommended Answers

All 4 Replies

Something else:

class HoldAttr(object):
    pass

a = HoldAttr()

print(hasattr(a, 'myattr1'))   # False

# create the attribute externally
# unless the class uses __slots__
a.myattr1 = []

print(hasattr(a, 'myattr1'))   # True

# test it
a.myattr1.append(1)

print(a.myattr1)  # [1]

That doesn't quite get me there.
Let me give some more context.

import randint

class HoldAttr(object): pass

aname = [HoldAttr() for x in range(10000)]

for i in range(500):
    aindex = random.randint(0, 999)
    try:
        aname[aindex].foundat.append(i)
    except AttributeError:
        aname[aindex].foundat = [i]

Most instances in aname will have no 'foundat' attribute. Some instances in aname may be "found" more than once. Trying not to initialize a 'foundat' attribute for every instance in aname.

I suggest using a cached property

class HoldAttr(object):

    @cached_property
    def foundat(self):
        return []

    @property
    def was_found(self):
        return "foundat" in self.__dict__

if __name__ == "__main__":
    h = HoldAttr()
    for i in range(3):
        h.foundat.append(i)
    print(h.foundat)
    print(h.was_found)
    h = HoldAttr()
    print(h.was_found)

""" my output -->
[0, 1, 2]
True
False
"""

However, a more classical style makes your code more readable

class HoldAttr(object):
    foundat = None

    def add_found(self, at):
        if self.foundat is None:
            self.foundat = [at]
        else:
            self.foundat.append(at)

    def was_found(self):
        return self.foundat is not None

if __name__ == "__main__":
    h = HoldAttr()
    for i in range(3):
        h.add_found(i)
    print(h.foundat)
    print(h.was_found())
    h = HoldAttr()
    print(h.was_found())

Code with straightforward behavior is better.

The cached property is definatly the best suggestion. If not using that, I would get in the habit of using try: except in these situations. That is syntactially simple and very common, so others reading your code will be able to deduce your intent from the code.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.