重写使用@property设置的属性

2024-03-29 07:59:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道在本例中如何更新使用@property decorator设置的属性。(下面的代码告诉你的不仅仅是文字……)

当我尝试在没有setter的情况下更新电子邮件时,我得到了AttributeError:cannotset attribute。当我使用setter时,没有任何变化。新邮件既不使用名字也不使用姓氏。你知道吗

有人能帮忙吗?你知道吗

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last

    @property
    def email(self):
        return f"{self.first}.{self.last}@email.com".lower()

    # @email.setter
    # def email(self, new_email):
    #     return new_email

Tags: 代码selfnewreturn属性emaildef情况
2条回答

我认为这里最直接的方法是去掉属性,改为使email成为一个可选参数,默认为first.last

class Employee:
    def __init__(self, first, last, email=None):
        self.first = first
        self.last = last
        self.email = email if email else f"{first}.{last}@email.com".lower()

现在,您可以使用常用的点符号修改现有实例的电子邮件地址:

>>> e = Employee('John', 'Doe')
>>> e.email
'john.doe@email.com'
>>>
>>> e.email = 'a@b.com'
>>> e.email
'a@b.com'

如果您真的想保留属性,那么setter需要更新实例属性:

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
        self._email = f"{first}.{last}@email.com".lower()

    @property
    def email(self):
        return self._email

    @email.setter
    def email(self, addr):
        self._email = addr

如果您需要在输入的过程中进行一些验证,例如,确认新电子邮件有@符号,则可以选择此模式:

    @email.setter
    def email(self, addr):
        if '@' not in addr:
            raise ValueError('nope!')
        self._email = addr

但除此之外,第一种选择要简单一些。你知道吗

在我的评论中,你需要确定新邮件是否在first.last@email.com中,然后设置firstlast属性。你知道吗

虽然我不会使用电子邮件作为属性,如果你是基于名称创建它,你应该改变名称本身。你知道吗

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last

    def email(self):
        return f"{self.first}.{self.last}@email.com".lower()

    def __repr__(self):
      return f"<Employee | {self.first} {self.last}>"

john = Employee('John', 'Smith')
print(john)
#<Employee | John Smith>
john.first = "Joe"
print(john)
#<Employee | Joe Smith>

否则,如果你想为电子邮件设置一个setter,那么我建议使用它来设置第一个和最后一个属性,但是你不需要返回值,因为你只是在设置你已经知道的电子邮件。我会使用re库来检查电子邮件的格式是否正确。这是一个非常粗略的例子:

@email.setter
def email(self, new_email):
    try:
        self.first, self.last = re.search('(?P<first>\w+).(?P<last>\w+)@\S+', email).group('first', 'last'))
    except AttributeError:
        raise ValueError("Email must be in "first.last@email.com")

相关问题 更多 >