如何创建可以后续访问的类实例?
我是一名高中生,刚开始学习编程,对计算机科学很感兴趣。我正在用迈克·道森的书《绝对初学者的Python编程学习(第三版)》自学Python编程。我正在写一个程序来练习我刚学到的面向对象编程(OOP)知识。这个程序模拟了一个银行,玩家可以在里面开银行账户、存取现金、获取汇率、从一个账户转账到另一个账户,还有其他功能。不过,我在这个程序上遇到了很大的困难,主要是关于如何让用户访问多个可用账户的部分。我不太确定这样做是否正确,但我尝试写了一个名为all_accounts的空列表作为类属性。每当创建一个账户时,就把这个账户实例添加到列表里。当玩家选择像存钱或取钱这样的菜单选项时,我想访问列表中的实例,以便修改对象的属性(比如余额)。但我完全不知道该怎么做,已经找了大约三天的答案,但没有找到任何有用的信息。请记住,我还是个初学者,所以我的代码可能写得不太好。我会把整个代码贴在下面,因为我觉得这样大家才能更好地理解代码是如何工作的。如果你发现我代码里有什么不对的地方,或者有什么可以改进的地方,请随时告诉我。我一直很乐意学习。
class Account(object):
"""An interactive bank account"""
wallet = 0
all_accounts = []
# initial
def __init__(self, ID, bal):
self.ID = ID
self.bal = bal
print("A new account has been opened!")
Account.all_accounts.append(self)
def withdraw(self, w_input):
if w_input < self.bal or w_input == 0:
print("That is not a valid amount. Sending you back to menu.\n")
Menu()
else:
self.bal = self.bal - w_input
print("You withdrew $" + str(w_input) + ".\n")
wallet += w_input
print("You wallet now contains $" + Account.wallet)
Menu()
def deposit(self):
# Whatever
def Menu():
print(
"""
0 - Leave the Virtual Bank
1 - Open a new account
2 - Withdraw money
3 - Deposit money
4 - Transfer money from one account to another
5 - Get exchange rates(Euro, Franc, Pounds, Yuan, Yen)
"""
) # Add more if necessary
choice = input("What would you like to do?: ")
while choice != "0":
if choice == "1":
account_name = input("What is your account's ID?: ")
account_bal = float(input("How much money would you like to put into the account?(USD): "))
account_name = Account(ID = account_name, bal = account_bal)
Menu()
elif choice == "2":
account_choice = input("What is your account ID?: ")
if account_choice in instance.Account.all_account:
withdraw_choice = input("How much money would you like to withdraw?: ")
account_choice.withdraw(w_input = withdraw_choice)
else:
print("Nope.")
if choice == "0":
print("\nThank you for visiting the virtual bank!")
input("Press the [ENTER] key to exit the program.")
Menu()
2 个回答
尽量把用户界面和应用程序的核心部分分开,正如ACEfanatic02所说的那样。
想想一个账户需要具备哪些东西:
- 一个独特的标识符
- 一个余额
- 客户的名字
- 一份交易记录
这些就是实例属性。
还要考虑账户需要能做些什么:
- 往账户里存钱
- 从账户里取钱
- 转账到另一个账户
这些就是方法。
你可能还想要一种方式来打印账户的文本表示。这可以通过给类提供一个特殊的方法 __str__
来实现。
一个简单的例子:
def _checkamount(a):
if a < 0:
raise ValueError('amount must be >0')
class Account(object):
maxnum = 0
def __init__(self, client):
self.client = client
self.balance = 0.0
self.transactions = []
Account.maxnum = Account.maxnum + 1
self.number = Account.maxnum
def __str__(self):
"Generate a human-readable representation of the Account."
rv = 'Accountnumber: ' + str(self.number) + '\n'
rv += 'Client: ' + str(self.client) + '\n'
rv += 'Balance: ' + str(self.balance) + '\n'
return rv
def withdraw(self, amount):
_checkamount(amount)
if self.balance < amount:
raise ValueError('overdraft!')
self.balance -= amount
self.transactions.append(("withdraw", amount))
def deposit(self, amount):
_checkamount(amount)
self.balance += amount
self.transactions.append(("deposit", amount))
def transfer(self, amount, other):
_checkamount(amount)
self.balance -= amount
self.transactions.append(("transfer", amount, other.number))
other.balance += amount
other.transactions.append(("transfer", amount, self.number))
我把这段代码保存在一个叫 account.py
的文件里。
一个交互式测试(使用 Ipython,非常推荐用于互动实验):
In [1]: from account import Account
In [2]: a = Account('myself')
In [3]: b = Account('someoneelse')
In [4]: a.deposit(200)
In [5]: a.withdraw(10)
In [6]: b.deposit(50)
In [7]: a.transfer(25, b)
In [8]: print a.transactions
[('deposit', 200), ('withdraw', 10), ('transfer', 25, 2)]
In [9]: print b
Accountnumber: 2
Client: someoneelse
Balance: 75.0
In [10]: print b.transactions
[('deposit', 50), ('transfer', 25, 1)]
In [11]: print a
Accountnumber: 1
Client: myself
Balance: 165.0
In [12]: a.withdraw(1000)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-ffc10f6333fe> in <module>()
----> 1 a.withdraw(1000)
/home/rsmith/tmp/account.py in withdraw(self, amount)
24 _checkamount(amount)
25 if self.balance < amount:
---> 26 raise ValueError('overdraft!')
27 self.balance -= amount
28 self.transactions.append(("withdraw", amount))
ValueError: overdraft!
在这个测试中,我用一个字符串作为 client
。由于Python的动态特性,我可以稍后把它改成一个 Client
类,只要这个类有一个 __str__
方法,代码依然可以正常工作。
一般来说,你希望把调用代码和你类内部的工作分开。让 Menu()
函数直接检查存放所有账户的列表,这样做不够灵活,以后可能会出现问题(比如,如果你把列表换成数据库存储怎么办?)
所以,像 AccountManager
这样的类可能是个更好的主意:
class AccountManager(object):
def __init__(self):
self.accounts = []
def create_account(self, id, balance):
# You may want to check for uniqueness of id's here as well
account = Account(id, balance)
self.accounts.append(account)
def get_account(self, id):
for account in self.accounts:
if account.id == id:
return account
return None # or a default value, or raise an exception
现在,调用代码只需要告诉 AccountManager
创建和获取账户,而不需要关心它们是怎么存储的。