如何在编程后创建可用于访问类实例的东西?

时间:2013-03-23 19:07:36

标签: python oop python-3.x

我是高中初级程序员,对计算机科学感兴趣。我一直在教自己使用Mike Dawson的书编写Python程序,学习为Python初学者编写第3版。我正在编写一个程序来练习我新获得的OOP知识。该程序模拟了一个银行,玩家可以在该银行开立银行账户,提取/存入现金,获得汇率,将资金从一个账户转移到另一个账户,以及其他功能。我遇到了程序的严重问题,作为程序的主要部分,模拟了用户可以访问的多个可访问帐户这一事实。我现在确定如何或者是否应该这样做,但我尝试编写一个类属性,这是一个名为all_accounts的空列表。每次实例化帐户时,实例都会附加到列表中。当玩家选择菜单选项(例如提取/存入现金)时,我希望访问列表中的实例,以便可以修改对象的属性(例如余额)。我不知道如何做到这一点,我一直在寻找约3天的答案而没有找到任何东西。请记住,我是一名初学程序员,所以我的代码可能会被认为编写得很糟糕。我将在下面发布完整的代码,因为我觉得有必要让人们完全了解代码的工作原理和功能。另外,请随时通知我我的代码中的任何其他内容不正确或我可以做得更好。我总是乐于学习。

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 个答案:

答案 0 :(得分:0)

通常,您希望将调用代码与类的内部工作隔离开来。使用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创建和检索帐户,并且不再关心它们的存储方式。

答案 1 :(得分:0)

尝试将用户界面与应用程序的内容分开,正如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__方法,代码仍然有效。