首页 > 解决方案 > python - 为什么在python OOP中将相同的对象附加到不同的列表时会得到不同的对象ID?

问题描述

我的 OOP 银行应用程序中有存款、取款和转账方法,这些方法似乎正在打印正确的值,但如果我删除repr方法,它会显示 1 ID 不相同。

编辑:我的其他课程,不确定是否相关:

class PersonError(Exception):
    """Person error."""
    pass


class TransactionError(Exception):
    """Transaction error."""
    pass


class Person:
    """Person class."""

    def __init__(self, first_name: str, last_name: str, age: int):
        """
        Person constructor.

        :param first_name: first name
        :param last_name: last name
        :param age: age, must be greater than 0
        """
        if not first_name or not last_name:
            raise PersonError
        else:
            self.first_name = first_name
            self.last_name = last_name

        self.bank_account = None
        if age <= 0:
            raise PersonError
        else:
            self._age = age

    @property
    def full_name(self) -> str:
        """Get person's full name. Combination of first and last name."""
        return f"{self.first_name} {self.last_name}"

    @property
    def age(self) -> int:
        """Get person's age."""
        return self._age

    @age.setter
    def age(self, value: int):
        """Set person's age. Must be greater than 0."""
        if value <= 0:
            raise PersonError
        else:
            self._age = value

    def __repr__(self) -> str:
        """
        Person representation.

        :return: person's full name
        """
        return self.full_name


class Bank:
    """Bank class."""

    def __init__(self, name: str):
        """
        Bank constructor.

        :param name: name of the bank
        """
        self.name = name
        self.customers = []
        self.transactions = []


    def add_customer(self, person: Person) -> bool:
        """
        Add customer to bank.

        :param person: person object
        :return: was customer successfully added
        """
        if person not in self.customers:
            self.customers.append(person)
            person.bank_account = Account(0, person, bank)
            return True
        else:
            return False

    def remove_customer(self, person: Person) -> bool:
        """
        Remove customer from bank.

        :param person: person object
        :return: was customer successfully removed
        """
        if person in self.customers:
            self.customers.remove(person)
            person.bank_account = None
            return True
        else:
            return False

    def __repr__(self) -> str:
        """
        Bank representation.

        :return: name of the bank
        """
        return self.name


class Transaction:
    """Transaction class."""

    def __init__(self, amount: float, date: datetime.date, sender_account: 'Account', receiver_account: 'Account',
                 is_from_atm: bool):
        """
        Transaction constructor.

        :param amount: value
        :param date: date of the transaction
        :param sender_account: sender's object
        :param receiver_account: receiver's object
        :param is_from_atm: is transaction from atm
        """
        self.is_from_atm = is_from_atm
        self.receiver_account = receiver_account
        self.sender_account = sender_account
        self.date = date
        self.amount = amount

    def __repr__(self) -> str:
        """
        Transaction representation.

        :rtype: object's values displayed in a nice format
        """
        if self.is_from_atm is True:
            return f"({self.amount} €) ATM"
        elif self.is_from_atm is False:
            return f"({self.amount} €) {self.sender_account.person} -> {self.receiver_account.person}"



我的方法:

class Account:
    """Account class."""

    def __init__(self, balance: float, person: Person, bank: 'Bank'):
        """
        Account constructor.

        :param balance: initial account balance
        :param person: person object
        :param bank: bank object
        """
        self.bank = bank
        self.person = person
        self._balance = balance
        self.number = f"EE{randint(111111111111111111, 999999999999999999)}"
        self.transactions = []

    @property
    def balance(self) -> float:
        """Get account's balance."""
        return self._balance

    def deposit(self, amount: float, is_from_atm: bool = True):
        """Deposit money to account."""
        if amount <= 0:
            raise TransactionError
        elif is_from_atm is True:
            t = Transaction(amount, date=datetime.date.today(), sender_account=self, receiver_account=self, is_from_atm=True)
            self._balance = self._balance + amount
            self.transactions.append(t)
            bank.transactions.append(t)
        elif is_from_atm is False:

            self._balance = self._balance + amount

    def withdraw(self, amount: float, is_from_atm: bool = True):
        """Withdraw money from account."""
        if amount <= 0 or amount > self._balance:
            raise TransactionError
        elif is_from_atm is True:
            t = Transaction(-amount, date=datetime.date.today(), sender_account=self, receiver_account=self, is_from_atm=True)
            self._balance = self._balance - amount
            self.transactions.append(t)
            bank.transactions.append(t)
        elif is_from_atm is False:

            self._balance = self._balance - amount

    def transfer(self, amount: float, receiver_account: 'Account'):
        """Transfer money from one account to another."""
        fee = 5
        if receiver_account == self:
            raise TransactionError
        elif (self._balance - fee - amount) < 0:
            raise TransactionError
        elif receiver_account.bank != self.bank and amount >= 0:
            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            self._balance = self._balance - amount - fee
            self.transactions.append(t)
            self.bank.transactions.append(t)

            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            receiver_account._balance = receiver_account._balance + amount
            receiver_account.transactions.append(t)
            receiver_account.bank.transactions.append(t)
        elif receiver_account.bank == self.bank and amount >= 0:
            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            self._balance = self._balance - amount
            self.transactions.append(t)
            self.bank.transactions.append(t)

            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            receiver_account._balance = receiver_account._balance + amount
            receiver_account.transactions.append(t)

如果名称是主要的:


if __name__ == '__main__':
    person = Person("Ago", "Luberg", 100)
    
    bank = Bank("TalBank")
    bank.add_customer(person)
    a1 = person.bank_account

    person2 = Person("Mati", "Maal", 90)
    bank.add_customer(person2)
    a2 = person2.bank_account
    
    a1.deposit(100)
    a2.deposit(100)
    a1.withdraw(10)
    a2.withdraw(50)
    a1.transfer(10, a2)
    
    
    print(a1.transactions)  # [(100 €) ATM, (-10 €) ATM, (10 €) Ago Luberg -> Mati Maal]
    print(a2.transactions)  # [(100 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
    print(bank.transactions)
    # [(100 €) ATM, (100 €) ATM, (-10 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]

打印交易时我的输出没有repr :

1. person1 transactions [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF340>]
2. person2 transactions [<__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF2B0>]
3. bank transactions(person1 + person2 transactions) [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]

没有repr方法的预期输出:

1. person1 transactions [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF340>]
2. person2 transactions [<__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]
3. bank transactions(person1 + person2 transactions) [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]

我的问题是为什么 person2 交易中的最后一个交易对象与 person1 和银行交易中的最后一个交易对象不同,尽管使用repr方法它们是相同的。

使用repr方法输出:

[(100 €) ATM, (-10 €) ATM, (10 €) Ago Luberg -> Mati Maal]
[(100 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
[(100 €) ATM, (100 €) ATM, (-10 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]

预先感谢任何希望在他们的帮助下做出贡献的人!赤红。

标签: pythonpython-3.xoop

解决方案


在这部分代码中:

elif receiver_account.bank != self.bank and amount >= 0:
            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            self._balance = self._balance - amount - fee
            self.transactions.append(t)
            self.bank.transactions.append(t)

            t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
                            is_from_atm=False)
            receiver_account._balance = receiver_account._balance + amount
            receiver_account.transactions.append(t)
            receiver_account.bank.transactions.append(t)

您要声明t两次:声明一次,然后将其附加到self.transactions,然后再声明一次(因此它等于另一个对象引用)并将其附加到receiver_account. 所以t第一次和第二次不是同一个对象。

删除第二个声明t应该会给您预期的结果。


推荐阅读