使用实例属性作为方法参数
我在尝试一段代码,但我搞不清楚当我把实例属性作为参数传给一个方法时,应该怎么修改这些属性。
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
看起来当我调用 buy
方法时,系统创建了一个新的变量 stockQty
。我本以为应该传递属性 qtyA
的引用,而不是它的值。这个问题可能和这个问题有关:我该如何通过引用传递变量?
我该如何解决这个问题呢?
4 个回答
我觉得你应该重新设计一下你的类。可以选择写几个函数,比如 buyA, buyB, buyC,并确保能重复使用一些共同的代码;或者把 buyA, buyB, buyC 合并成一个字典,然后用一个统一的函数 buy 来更新这个字典,更新时用字符串作为索引。
第一个建议只有在 A、B 和 C 在你的类中有特别的业务逻辑意义时才有意义。
一种简单的方法是把你想修改的成员名称作为字符串传入,比如说“qtyA”,然后用 getattr(self, stockQty)
来读取这个值,用 setattr(self, stockQty, newVal)
来改变这个值。
如果你觉得直接传字符串不太好,可以定义一些类变量,比如 refQtyA = "qtyA"
,然后在调用函数的时候用这些变量作为参数,比如 buy(p.refQtyA, 10, 25)
。
这个问题可能和这个问题有关:Python:我怎么通过引用传递一个变量?
确实是。
我该如何解决这个问题呢?
你需要传递一个可以被修改的值,并对其进行修改。数字是不能被直接修改的:比如说,a
可以从指向 23
变成指向 42
,但你不能让 23
变成 42
,或者反过来。
在你的情况下,自然的解决办法是注意到你正在做的另一个傻事——同时使用一堆相关的、名字相似的变量——并把它们替换成一个序列。list
类型是一个可以修改的序列。你需要传递整个列表,而不是仅仅一个数字,并指明要替换列表中的哪个元素。不过其实你不需要传递列表,因为它已经是 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
为了更灵活的解决方案,你可以考虑在股票名称和股票数量之间建立一种关联——毕竟,谁知道客户将来可能想要哪些股票呢。我们可以简单地使用 dict
来实现这一点。
(固定的“佣金”费用也不太现实;用百分比来计算更合理。)