2

I am currently wondering why this modest piece of code has an output I'm not expecting:

class Product(object):
    price = 0

    def __init__(self, tmp_price):
        self.price = tmp_price

class Market(object):
    products = []

    def __init__(self):
        self.products.append(Product(10))

a = Market()
b = Market()

print a.products[0]
print b.products[0]
print len(a.products)

Indeed, I get some output like:

<__main__.Product object at 0x7fe5899e46d0>
<__main__.Product object at 0x7fe5899e46d0>
2

Does anyone have an explanation? I guess it has something to do with python's way to handle references and all but...

weadmonkey
  • 103
  • 1
  • 4

5 Answers5

5

The problem is in this part of your code:

class Market(object):
    products = []  # products belongs to the class and is shared by all instances!
    def __init__(self):
        self.products.append(Product(10)) # appending to the 'products' class atribute

The products attribute belongs to the class and is shared by all instances. Class attributes are accessible from all instances of the class. When you reference products from self (self.products), Python does not find products belonging to the instance, so then it looks in to see if products can be found in the class.

What you really want is this:

class Market(object):
    def __init__(self):
        self.products = []  # products belongs to the instance
        self.products.append(Product(10))

See also Python: Difference between class and instance attributes

Community
  • 1
  • 1
Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
4

You are referencing static class variables.

Static class variables in Python THere is lots of information about it online!

Market.products[0] is the actual value.

This is not the same as an instance variable as you found out. http://legacy.python.org/doc/essays/ppt/acm-ws/sld051.htm

Community
  • 1
  • 1
dm03514
  • 54,664
  • 18
  • 108
  • 145
3

It's because you're printing the objects reference, not the value of its field;

Try changing

print a.products[0]
print b.products[0]

to

print a.products[0].price
print b.products[0].price
Russ Clarke
  • 17,511
  • 4
  • 41
  • 45
  • 2
    Actually my point was that both a.products[0] and b.products[0] are the same, they are the same reference. – weadmonkey Mar 18 '12 at 00:27
  • Ahh yes, good point - it's because your self.products field is static. a.products == b.products will be True. dm03514 has the link to the info in his answer. – Russ Clarke Mar 18 '12 at 00:35
  • 1
    @Russ C: I think "static" is the wrong word here because `Market.products` made to refer to a different object. I would prefer "class attribute" or "shared". – Steven Rumbalski Mar 18 '12 at 00:47
  • Fair enough, I'm just using the C# definition of static out of habit rather then anything else. – Russ Clarke Mar 18 '12 at 00:51
2

Because in Market init, self.products is using Market class member products, it shared between all Market's instance.

PasteBT
  • 2,128
  • 16
  • 17
1

That is the default way Python implements the _str_() function:

<module-name>.<class-name> <type> at <memory-address>

If you don't like this representation, you can always give your own implementation of _str_(). The memory-addresses are provided as a way for you to check if two variables actually point to the same item.

Kaustubh Karkare
  • 1,083
  • 9
  • 25