0

Why variables declared outside init method do not posses additivity property? For example i have the following class:

class Trade:
    allTrades = []
    netPosition = 0

    def __init__(self, qty):
        self.quantity = qty

        self.allTrades.append(self.quantity)
        self.netPosition += self.quantity

allTrades (empty list) and netPosition variables are defined outside the init method while quantity variable defined inside.

Next I create 2 objects of my class and print AllTrades and netPosition for either of them:

deal1=Trade('long', 50, 31)
deal2=Trade('long', 16, 39)

print(deal2.allTrades)
print(deal2.netPosition)

And as far as I see allTrades (list) variable is additive while netPosition is not: print(deal2.allTrades) returns [50, 16]. And print(deal2.netPosition) returns 16 however I assume that it should return 66

How can I make print(deal2.netPosition) return 66 instead of 16?

1
  • lists are mutable, ints are not. Commented Jul 1, 2021 at 17:12

1 Answer 1

1

Your __init__ function creates two object variables which are references to the class variables of the same name. So far so good.

When you call self.allTrades.append you are modifying (or mutating) your allTrades object, which is shared between all the objects of your class.

When you do self.netPosition += you are not modifying netPosition because numbers are immutable. Instead you're replacing your reference with another one to a different number object. That means you've broken the connection between your object variable and your class variable. No other objects will see those changes.

To get what you expect, you need to put your number inside another mutable object.

netPosition = [0]

self.netPosition = netPosition

self.netPosition[0] += self.quantity
Sign up to request clarification or add additional context in comments.

2 Comments

It's more than just the immutability of integers. No instance attribute named allTrades is ever created. Rather, self.allTrades resolves to Trade.allTrades in the absence of an instance attribute by that name. For self.netPosition, the situation is a little tricker, but I think the result is self.netPosition = Trade.netPosition.__iadd__(self.quantity), where the class attribute is used to produce a value to assign to a new instance attribute that will shadow the class attribute.
@chepner you're right, I was imagining an assignment there that didn't actually exist. My bad.

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.