I have this code I am trying out and I can't figure out how to modify the instance attributes when I use them as parameters when calling a method.
class Portfolio(object):
def __init__(self):
self.qtyA = 50
self.qtyB = 0
self.qtyC = 0
self.cash = 0
def __str__(self):
return ("%d %d %d %.2f")%(self.qtyA, self.qtyB, self.qtyC, self.cash)
def buy(self, stockQty, qtyToBuy, price, commission=20):
stockQty += qtyToBuy
print stockQty
buyTransaction = price * qtyToBuy
self.cash -= buyTransaction + commission
>>> p = Portfolio()
>>> p.buy(p.qtyA,10,25)
60
>>> print p
50 0 0 -270.00
What seems to be happening is that a new variable stockQty
is being created when buy
is called. I would expect that a reference to the attribute qtyA
would be passed instead of the value. This problem might be related to this question: H开发者_如何学Cow do I pass a variable by reference?
How can I work around this issue?
This problem might be related to this question: Python: How do I pass a variable by reference?
It is.
How can I work around this issue?
You need to pass a value that can be modified, and modify it. Numbers cannot be modified: a
can be changed from referring to 23
to referring to 42
instead, but you cannot cause 23
to become 42
or vice-versa.
In your case, the natural way to do this is to also notice the other silly thing you're doing - using a bunch of related, similarly-named variables in parallel - and fix that as well, by replacing them with a sequence. The list
type is a modifiable sequence. You need to pass the list itself instead of just a numeric quantity, and indicate which element of the list to replace. Except you don't actually need to pass the list, because it's already a part of self
.
class Portfolio(object):
def __init__(self):
self.quantity = [50, 0, 0]
self.cash = 0
def __str__(self):
return ("%d %d %d %.2f")%(self.quantity[0], self.quantity[1], self.quantity[2], self.cash)
def buy(self, stockToBuy, amountToBuy, price, commission=20):
self.quantity[stockToBuy] += amountToBuy
cost = price * amountToBuy
self.cash -= cost + commission
For a more flexible solution, you might consider the idea of having an association between stock names and quantities of stock - after all, who knows what stocks the client might want in the future. We can do this simply by using a dict
instead.
(A constant 'commission' cost is also unrealistic; a percentage makes more sense.)
A simple approach would be to pass in strings as stockQty containing the name of the member you want to modify (e.g. "qtyA"), and use getattr(self, stockQty)
to read and setattr(self, stockQty, newVal)
to change the value of this parameter.
If you are not happy about passing in free form strings, you can define some class variables, e.g. refQtyA = "qtyA"
, and use them as your parameters when you call your function: buy(p.refQtyA, 10, 25)
.
As @vhallac
mentioned you can use setattr
or getattr
methods to set and get value of attribute respectively. In fact you do not need to pass the object attribute to the function. you can directly access it in the function and update it.:
def buy(self, qtyToBuy, price, commission=20):
self.qtyA += qtyToBuy
print self.qtyA
buyTransaction = price * qtyToBuy
self.cash -= buyTransaction + commission
>>> p = Portfolio()
>>> p.buy(10,25)
>>> print p
60 0 0 -270.00
I think you should redesign your class. Either write functions buyA, buyB, buyC and make sure to reuse the common code, or refactor buyA, buyB, buyC to a single dictionary which would be updated using a single function buy indexed by a string.
The first proposal is meaningful only if A,B and C have some special business logic meaning in your class.
精彩评论