首页 > 解决方案 > 使用属性装饰器时类属性不更新

问题描述

我正在尝试使用属性装饰器来验证 python 对象。

以下是我的课

'''Contains all model classes. Each class corresponds to a database table'''

from validation import company_legal_type, max_len

class Company():
    '''A class to represent a company and its basic information'''
    
    def __init__(self, ref, name, currency, legal_type, business):
        self._ref = int(ref)
        self._name = name
        self._currency = str(currency) # i.e. The functional currency
        self._legal_type = str(legal_type)
        self._business = str(business)
    
    def __str__(self):
        return f"Company object for '{self._name}'"
    
    # Validate object attributes

    @property # Prevents change to ref after company object has been created
    def ref(self):
        return self._ref

    @property # The following two functions permit changes but set validation checks for name
    def name(self):
        return self._name
    
    @name.setter
    def name(self, value):
        if type(value) != str:
            raise TypeError("Company name must be a string.")
        if len(value) > max_len['company_name']:
            raise ValueError(f"Company name must not be longer than {str(max_len['company_name'])} characters.")

以下是validation.py

# data length validation
max_len = {
    'company_name': 200,
    'company_business': 200,
}

最后是我如何使用这个类:

# Import custom modules
from models import Company, Currency

company = Company(23, 'ABC Limited', 'PKR', 'pvt_ltd', 'manufacturing')    
company.name = 'ABCD Limited'

print(company.name)

这将打印“ABC Limited”而不是“ABCD Limited”。

如果我在更新 company.name 时破坏了验证条件,例如使用整数而不是字符串,则会正确导致错误。但是如果我在创建对象时破坏它,则不会引发错误。

我究竟做错了什么?

标签: pythonclass

解决方案


问题是你的二传手没有设置任何东西。它只会在输入错误时引发错误。所以你必须实际设置一些东西,否则你希望它如何修改self._name?所以:

@name.setter
def name(self, value):
    if type(value) != str:
        raise TypeError("Company name must be a string.")
    if len(value) > max_len['company_name']:
        raise ValueError(f"Company name must not be longer than {str(max_len['company_name'])} characters.")
    self._name = value

如果我在更新 company.name 时破坏了验证条件,例如使用整数而不是字符串,则会正确导致错误。但是如果我在创建对象时破坏它,则不会引发错误。

因为您不使用__init__. 通常,如果您有验证属性设置器,您希望使用__init__. 所以你__init__应该是这样的:

def __init__(self, ref, name, currency, legal_type, business):
    self._ref = int(ref)
    self.name = name
    self._currency = str(currency) # i.e. The functional currency
    self._legal_type = str(legal_type)
    self._business = str(business)

推荐阅读