You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AttributeError: 'Seller'对象无'regon'属性问题排查求助

问题分析:Seller类继承Client后抛出AttributeError异常

问题描述

实现了继承自Client类的Seller类,代码逻辑看似正确,但测试时始终抛出错误:AttributeError: 'Seller' object has no attribute 'regon'。以下是相关类代码及报错回溯信息:

Seller类代码

from src.invoice_generator.models.client import Client


class Seller(Client):
    """
    Seller model

    Attributes:
        :param name: str - seller name
        :param street: str - seller street
        :param city: str - seller city
        :param postal_code: str - seller postal code
        :param phone: str - seller phone number
        :param email: str - seller email address
        :param nip: str - seller NIP number
        :param regon: str - seller REGON number
        :param bank_account: str - seller bank account number

    Methods:
        :__init__: initialize Seller object
        :__str__: return string representation of Seller object
    """

    def __init__(self, name: str, street: str, city: str, postal_code: str, phone: str, email: str, nip: str, regon: str, bank_account: str) -> None:
        super().__init__(name, street, city, postal_code, phone, email, nip)
        self.regon = regon
        self.bank_account = bank_account

        if not self.validate():
            if not self.validate_regon():
                raise ValueError('Invalid REGON number')
            if not self.validate_bank_account():
                raise ValueError('Invalid bank account number')

    def __str__(self) -> str:
        return f'super().__str__(), {self.regon}, {self.bank_account}'

    def validate(self) -> bool:
        """
        Validate Seller object
        :return: bool - True if Seller object is valid, False otherwise
        """
        return super().validate() and self.validate_regon() and self.validate_bank_account()

    def validate_regon(self) -> bool:
        """
        Validate REGON number
        :return: bool - True if REGON number is valid, False otherwise
        """
        regon = self.regon.replace('-', '')
        if len(regon) != 9:
            return False
        weights = [8, 9, 2, 3, 4, 5, 6, 7]
        check_sum = sum([int(regon[i]) * weights[i] for i in range(len(weights))])
        return check_sum % 11 == int(regon[-1])

    def validate_bank_account(self) -> bool:
        """
        Validate bank account number
        :return: bool - True if bank account number is valid, False otherwise
        """
        bank_account = self.bank_account.replace('-', '')
        if len(bank_account) != 26:
            return False
        weights = [1, 10, 3, 30, 9, 90, 27, 76, 81, 34, 49, 5, 50, 15, 53, 45, 62, 38, 89, 17, 73, 51, 25, 56, 75, 71]
        check_sum = sum([int(bank_account[i]) * weights[i] for i in range(len(weights))])
        return check_sum % 97 == 1

Client类代码

import re


class Client:
    """
    Client model

    Attributes:
        :param name: str - client name
        :param street: str - client street
        :param city: str - client city
        :param postal_code: str - client postal code
        :param phone: str - client phone number
        :param email: str - client email address
        :param nip: str - client NIP number

    Methods:
        :__init__: initialize Client object
        :__str__: return string representation of Client object
    """

    def __init__(self, name: str, street: str, city: str, postal_code: str, phone: str, email: str, nip: str = '') -> None:
        self.name = name
        self.street = street
        self.city = city
        self.postal_code = postal_code
        self.phone = phone
        self.email = email
        self.nip = nip

        if not self.validate():
            if not self.validate_nip():
                raise ValueError('Invalid NIP number')
            if not self.validate_email():
                raise ValueError('Invalid email address')
            if not self.validate_phone():
                raise ValueError('Invalid phone number')

    def __str__(self) -> str:
        return f'{self.name}, {self.street}, {self.city}, {self.postal_code}, {self.phone}, {self.email}, {self.nip}'

    def validate_nip(self) -> bool:
        """
        Validate NIP number
        :return: bool - True if NIP number is valid, False otherwise
        """
        nip = self.nip.replace('-', '')
        if len(nip) != 10:
            return False
        weights = [6, 5, 7, 2, 3, 4, 5, 6, 7]
        check_sum = sum([int(nip[i]) * weights[i] for i in range(len(weights))])
        return check_sum % 11 == int(nip[-1])

    def validate_email(self) -> bool:
        """
        Validate email address
        :return: bool - True if email address is valid, False otherwise
        """
        return bool(re.match(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$', self.email))

    def validate_phone(self) -> bool:
        """
        Validate phone number
        :return: bool - True if phone number is valid, False otherwise
        """
        self.phone = self.phone.replace(' ', '')
        self.phone = self.phone.replace('-', '')
        is_valid = bool(re.match(r'^\+?1?\d{9,15}$', self.phone))

        return is_valid

    def validate_postal_code(self) -> bool:
        """
        Validate postal code
        :return: bool - True if postal code is valid, False otherwise
        """
        self.postal_code = self.postal_code.replace(' ', '')
        self.postal_code = self.postal_code.replace('-', '')
        is_valid = bool(re.match(r'^\d{2}\d{3}$', self.postal_code))

        return is_valid

    def validate(self) -> bool:
        """
        Validate client
        :return: bool - True if client is valid, False otherwise
        """
        return self.validate_nip() and self.validate_email() and self.validate_phone() and self.validate_postal_code()

报错回溯信息

Traceback (most recent call last):
  File "/home/sosaymon/Projects/invoice-generator/src/invoice_generator/invoice-generator.py", line 4, in <module>
    seller: Seller = Seller("John Doe", "Street 1", "City", "00-000", "123456789", "test@test.pl", "6110202860","23017921600000", "87819510197411291315601703")
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sosaymon/Projects/invoice-generator/src/invoice_generator/models/seller.py", line 25, in __init__
    super().__init__(name, street, city, postal_code, phone, email, nip)
  File "/home/sosaymon/Projects/invoice-generator/src/invoice_generator/models/client.py", line 31, in __init__
    if not self.validate():
           ^^^^^^^^^^^^^^^
  File "/home/sosaymon/Projects/invoice-generator/src/invoice_generator/models/seller.py", line 43, in validate
    return super().validate() and self.validate_regon() and self.validate_bank_account()
                                  ^^^^^^^^^^^^^^^^^^^^^
  File "/home/sosaymon/Projects/invoice-generator/src/invoice_generator/models/seller.py", line 50, in validate_regon
    regon = self.regon.replace('-', '')
            ^^^^^^^^^^
AttributeError: 'Seller' object has no attribute 'regon'

Process finished with exit code 1

错误原因

核心是初始化顺序错误:

  1. 创建Seller实例时,先执行super().__init__()调用父类Client的构造函数
  2. Client的构造函数中会调用self.validate(),但因为Seller重写了validate方法,实际执行的是Seller类的validate方法
  3. Seller的validate方法会调用self.validate_regon(),此时Seller类中self.regon = regon这行代码还没执行,实例没有regon属性,因此抛出AttributeError

修复方案

调整Seller构造函数的执行顺序,先初始化子类独有的属性,再调用父类构造函数,这样父类构造函数触发validate时,子类属性已经存在:

修改后的Seller.__init__代码:

def __init__(self, name: str, street: str, city: str, postal_code: str, phone: str, email: str, nip: str, regon: str, bank_account: str) -> None:
    # 先初始化子类特有的属性
    self.regon = regon
    self.bank_account = bank_account
    # 再调用父类构造函数
    super().__init__(name, street, city, postal_code, phone, email, nip)

    if not self.validate():
        if not self.validate_regon():
            raise ValueError('Invalid REGON number')
        if not self.validate_bank_account():
            raise ValueError('Invalid bank account number')

内容的提问来源于stack exchange,提问作者SoSaymon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 05:09:49