Python 重写使用@property设置的属性

Python 重写使用@property设置的属性,python,Python,我想知道在这种情况下如何更新使用@property decorator设置的属性。(下面的代码将告诉您的不仅仅是文字……) 当我尝试在没有设置器的情况下更新电子邮件时,我得到了一个AttributeError:can't set属性。当我使用setter时,没有任何变化。新邮件既不使用名字也不使用姓氏 有人能帮忙吗 class Employee: def __init__(self, first, last): self.first = first sel

我想知道在这种情况下如何更新使用@property decorator设置的属性。(下面的代码将告诉您的不仅仅是文字……)

当我尝试在没有设置器的情况下更新电子邮件时,我得到了一个AttributeError:can't set属性。当我使用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

正如我在我的评论中所发布的,您需要首先确定新电子邮件是否在
中。last@email.com
然后只需设置
first
last
属性

虽然我不会使用电子邮件作为属性,如果你是基于名称创建的,你应该更改名称本身

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>

我认为这里最简单的方法是去掉属性,而将
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

但是,除此之外,第一个选项更简单。

您应该使用第一个和最后一个属性来更改电子邮件,否则您需要确保设置为第一个时的电子邮件。last@email.com格式化然后设置这些属性,然后诚实地说,您应该只返回None或根本没有return语句,因为这意味着None return。尽管说实话,你最终还是要决定你想在这里使用什么逻辑,要么你决定先发邮件,要么最后发邮件,要么它们是分开的;显式设置电子邮件地址实际上没有意义。如果没有明确的地址设置,
email.com
地址应该是默认地址吗?非常感谢,克里斯。我唯一不清楚的是单下划线的用法:我只能注意到,如果我删除它,我会得到一个递归错误,尽管我一直认为单下划线纯粹是常规的,不会影响代码的行为(除非使用*导入)。显然情况并非如此……正如你所说,下划线是惯例。如果删除它,则会创建一种情况,其中有两个名称相同的东西:email属性和email属性。这种重复会产生歧义-当您引用
employee.email
时,您是引用实例变量还是属性?因此,它们需要单独的名称。希望能有帮助。我是编程新手,但可能也有点笨…:当我使用“\u email”时,复制属性/属性仍然保留。我很困惑。看看这条老线索,很好地解释了属性以及它们如何在引擎盖下工作:
    @email.setter
    def email(self, addr):
        if '@' not in addr:
            raise ValueError('nope!')
        self._email = addr