0

I have a list of objects, known as Bricks, I want to check the attributes of all objects in the list. I tried:

pos = [Brick.start_pos for Brick in self.brick_list]

to create a list of the required attribute i.e start_pos, but it populates a list with only the attribute of the last brick in the brick_list. I am using python 3.4. I need to do this for a lot of different attributes so a comprehension makes sense to me.

Brick class is mostly just a holder for data and is defined:

class Brick:
    def __init__(self, start_pos=0, current_pos=0, variety=0, moveability=0, 
                 neighbours=0, max_range=0, sides=0, rotation=0, length=0,
                 previous_pos =0):
        self.start_pos = start_pos
        self.current_pos = current_pos
        self.moveability = moveability
        self.variety = variety
        self.neighbours = neighbours
        self.max_range = max_range
        self.sides = sides
        self.rotation = rotation
        self.length = length
        self.previous_pos = previous_pos

with couple very simple functions.

8
  • 3
    How did you define the class Brick? And how did you build the list? Commented Aug 5, 2015 at 11:30
  • The list is held as an attribute in another class. It is built by hell.brick_list = len(lister)*[Brick()] Commented Aug 5, 2015 at 11:34
  • 2
    The fragment that you have is a 100% correct list comprehension which yields the attributes of all the bricks in the brick_list (as long as accessing that attribute doesn't modify the list as a side effect). If it isn't giving you what you expect -- the problem is probably that the list isn't what you think that it is. Commented Aug 5, 2015 at 11:36
  • 1
    How did you build self.brick_list ? Commented Aug 5, 2015 at 11:38
  • 1
    @Elwood168 It appears the list contains the same Brick instance, repeated n times (n being the length of lister). Commented Aug 5, 2015 at 11:41

1 Answer 1

3

It appears the list contains the same Brick instance, repeated n times (n being the length of lister)

hell.brick_list = len(lister)*[Brick()] 

instead, you might want to build the list as

hell.brick_list = [Brick() for _ in lister] 

Obviously, you will need to pass the constructor all the necessary parameters, otherwise you would end-up with Bricks with identical attributes (default values).

Actually, given your second comment

for i in range (len(lister)): hell.brick_list[i].start_pos = lister[i]

the best option would be to create and initialize the list all in one go

hell.brick_list = [Brick(start_pos=pos) for pos in lister]
Sign up to request clarification or add additional context in comments.

4 Comments

It's worth noting that, in the first (non-working) version, this means that in the line for i in range (len(lister)): hell.brick_list[i].start_pos = lister[i] each time you assign a value to start.pos it is assigned to all copies of the same Brick instance, because they are all the same object.
@Pynchia. Thanks for the explanation, I did not understand that could happen. I replaced that line with what you suggested and it all worked immediately, very satisfying :)
[Brick()] is evaluated and it produces a list containing a single object instance. Then the list is multiplied by len(lister), which produces a list containing the very same elements, but repeated len(lister) times over. Only one Brick object instance is created.
@SiHa yes. And thank you for mentioning that, I had not noticed the OP's second comment, so you allowed me to improve my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.