We're a community of 1077K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,076,263 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

if attribute exists: append; else: create

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.

4
Contributors
4
Replies
9 Hours
Discussion Span
6 Months Ago
Last Updated
5
Views
shayallenhill
Newbie Poster
4 posts since Nov 2012
Reputation Points: 0
Solved Threads: 0
Skill Endorsements: 0

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]
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

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.

shayallenhill
Newbie Poster
4 posts since Nov 2012
Reputation Points: 0
Solved Threads: 0
Skill Endorsements: 0

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.

Gribouillis
Posting Maven
Moderator
3,101 posts since Jul 2008
Reputation Points: 1,130
Solved Threads: 761
Skill Endorsements: 11

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.

hughesadam_87
Posting Whiz in Training
274 posts since May 2009
Reputation Points: 67
Solved Threads: 12
Skill Endorsements: 1

This article has been dead for over three months: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
 
© 2013 DaniWeb® LLC
Page rendered in 0.0656 seconds using 2.69MB