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
错误原因
核心是初始化顺序错误:
- 创建Seller实例时,先执行
super().__init__()调用父类Client的构造函数 - Client的构造函数中会调用
self.validate(),但因为Seller重写了validate方法,实际执行的是Seller类的validate方法 - 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
相关产品推荐
相关产品推荐

