Python 方法属性并没有自我更新,即使我给它指定了一个不同的值

Python 方法属性并没有自我更新,即使我给它指定了一个不同的值,python,class,Python,Class,更新值时,_init__方法仍然使用旧的属性值 class Email: def __init__(self, name): self.name = name self.email = self.name + "@hotmail.com" def details(self): return f'{self.name} | {self.email}' person = Email("James") print(person.det

更新值时,_init__方法仍然使用旧的属性值

class Email:
    def __init__(self, name):
        self.name = name
        self.email = self.name + "@hotmail.com"

    def details(self):
        return f'{self.name} | {self.email}'

person = Email("James")
print(person.details())

person.name = "Michael"
print(person.details())
获得的输出:

James | James@hotmail.com
Michael | James@hotmail.com
预期产出:

James | James@hotmail.com
Michael | Michael@hotmail.com
我做错了什么?

在本例中,self.email被分配到类的_init__方法中,该方法仅在创建电子邮件实例时调用。因此,重新分配self.name时,self.email不会更改。要解决此问题,可以使用属性装饰器:

class Email:
  def __init__(self, name):
    self._name = name
    self._email = f'{name}@hotmail.com'
  def details(self):
    return f'{self._name} | {self._email}'
  @property
  def name(self):
    return self._name
  @name.setter
  def name(self, _new_name):
    self._name = _new_name
    self._email = f'{_new_name}@hotmail.com'

person = Email("James")
print(person.details())
person.name = "Michael"
print(person.details())
输出:

James | James@hotmail.com
Michael | Michael@hotmail.com
在本例中,self.email被分配到类的_init__方法中,该方法仅在创建电子邮件实例时调用。因此,重新分配self.name时,self.email不会更改。要解决此问题,可以使用属性装饰器:

class Email:
  def __init__(self, name):
    self._name = name
    self._email = f'{name}@hotmail.com'
  def details(self):
    return f'{self._name} | {self._email}'
  @property
  def name(self):
    return self._name
  @name.setter
  def name(self, _new_name):
    self._name = _new_name
    self._email = f'{_new_name}@hotmail.com'

person = Email("James")
print(person.details())
person.name = "Michael"
print(person.details())
输出:

James | James@hotmail.com
Michael | Michael@hotmail.com

正如@Ajax1234所说,当您创建一个新实例时,init函数正在调用。如果您熟悉面向对象语言,请将其视为构造函数

因此,如果您只是更改person.name,您可以更改name字段,但不能更改分配了旧name值的email变量

关于该案例,您有几个选择:

您可以创建一个名为Michael的新电子邮件对象

您可以直接重新分配电子邮件,就像在init函数中一样

您可以为setNamename之类的名称创建setter方法,并且可以在此函数中更新电子邮件。因此,当您呼叫setter时,它会自动更新电子邮件


正如@Ajax1234所说,当您创建一个新实例时,init函数正在调用。如果您熟悉面向对象语言,请将其视为构造函数

因此,如果您只是更改person.name,您可以更改name字段,但不能更改分配了旧name值的email变量

关于该案例,您有几个选择:

您可以创建一个名为Michael的新电子邮件对象

您可以直接重新分配电子邮件,就像在init函数中一样

您可以为setNamename之类的名称创建setter方法,并且可以在此函数中更新电子邮件。因此,当您呼叫setter时,它会自动更新电子邮件


最简单的修复方法是将电子邮件设置为属性,而不是在uuu init_uuuuuuuu中设置的属性


最简单的修复方法是将电子邮件设置为属性,而不是在uuu init_uuuuuuuu中设置的属性

手术中出了什么问题? 如果我们在您使用person=EmailJames行实例化person对象之后立即打开它,它将是这样的:

person {
"name"  : "James", 
"email" : "James@hotmail.com"
}
如果我们像处理person.name=Michael一样更新此person对象中的name变量,并再次打开person对象,则会是:

person {
"name"  : "Michael", 
"email" : "James@hotmail.com"
}
请注意,在这个阶段,它仍然是我们前面实例化的同一个人对象,并且email变量没有改变它以前的状态,因为我们还没有对它做任何更改

通过将email字段设置为属性,并使用name变量动态地设置它,它非常好而且干净。以下是@chepner代码的副本:

class Email:

    def __init__(self, name):
        self.name = name
        # self.email = self.name + "@hotmail.com"

    @property
    def email(self):
        return f'{self.name}@hotmail.com'

    def details(self):
        return f'{self.name} | {self.email}'
什么是财产,如何使用? 属性是Python,属性对象具有以下方法:

getter:用于获取属性值 setter:用于设置属性值 删除器:用于删除属性值 现在,到底发生了什么?使用以下行,我们将电子邮件设置为属性:

这个修饰过的函数也可以用作getter,例如person.email

请注意,在这里,我们没有将其链接到中所示的变量,如果我们想要/需要,可以通过替换return语句并在uu init_uu中设置一个_email变量来实现:

然后,对于setter和deleter,我们可以将它们创建为:

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

    @email.deleter
    def email(self):
        del self._email
请注意,getter、setter和deleter方法都与属性具有相同的名称,只是不同的decorator

根据问题描述,不需要单独支持更新电子邮件地址,但如果我们运行person.email=Michael@hotmail.com,因为电子邮件是一个属性,所以它会触发setter将值设置为_email变量

返回到中的详细信息方法:

通过执行self.email,我们触发getter返回电子邮件地址,该地址在return语句return f'{self.name}@hotmail.com'中动态生成。

操作中出现了什么错误? 如果我们在您使用person=EmailJames行实例化person对象之后立即打开它,它将是这样的:

person {
"name"  : "James", 
"email" : "James@hotmail.com"
}
如果我们像处理person.name=Michael一样更新此person对象中的name变量,并再次打开person对象,则会是:

person {
"name"  : "Michael", 
"email" : "James@hotmail.com"
}
请注意,在这个阶段,它仍然是我们前面实例化的同一个人对象,并且email变量没有改变它以前的状态,因为我们还没有对它做任何更改

通过将email字段设置为属性,并将其设置为dynamica,它非常漂亮且干净 使用name变量。以下是@chepner代码的副本:

class Email:

    def __init__(self, name):
        self.name = name
        # self.email = self.name + "@hotmail.com"

    @property
    def email(self):
        return f'{self.name}@hotmail.com'

    def details(self):
        return f'{self.name} | {self.email}'
什么是财产,如何使用? 属性是Python,属性对象具有以下方法:

getter:用于获取属性值 setter:用于设置属性值 删除器:用于删除属性值 现在,到底发生了什么?使用以下行,我们将电子邮件设置为属性:

这个修饰过的函数也可以用作getter,例如person.email

请注意,在这里,我们没有将其链接到中所示的变量,如果我们想要/需要,可以通过替换return语句并在uu init_uu中设置一个_email变量来实现:

然后,对于setter和deleter,我们可以将它们创建为:

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

    @email.deleter
    def email(self):
        del self._email
请注意,getter、setter和deleter方法都与属性具有相同的名称,只是不同的decorator

根据问题描述,不需要单独支持更新电子邮件地址,但如果我们运行person.email=Michael@hotmail.com,因为电子邮件是一个属性,所以它会触发setter将值设置为_email变量

返回到中的详细信息方法:


通过执行self.email,我们触发getter返回电子邮件地址,该地址是在return语句return f'{self.name}@hotmail.com'中动态生成的。

相关,可能重复:它更改了您告诉它的名称。创建实例后,代码中的任何内容都不会创建新的电子邮件。相关的,可能是重复的:它会按照您的说明更改名称。创建实例后,您的代码中没有任何内容会创建新的电子邮件。将电子邮件作为属性,根据当前名称按需计算电子邮件地址,将更简单,更符合原始问题的预期。我只是绞尽脑汁,我理解那里发生了什么,谢谢!将电子邮件作为财产,根据当前名称按需计算电子邮件地址,将更简单,更符合原始问题的预期。我只是绞尽脑汁,我理解那里发生了什么,谢谢!非常感谢,我花了一些时间,但我想我明白了,init方法只在创建对象时执行,因此即使我更改了name属性,属性email也不会更新,但是通过使用@property创建自己的方法,我可以将其作为属性调用,并通过从init获取值来强制更新,对吗?是的;电子邮件不再是一个固定值,而是使用当前的名称按需计算。非常感谢,这花了我一段时间,但我想我得到了它,init方法仅在创建对象时执行,因此即使我更改了name属性,属性email也不会被更新,但是通过使用@property创建自己的方法,我可以将其作为属性调用,并通过从init获取值来强制更新,对吗?是的;电子邮件不再是一个固定值,而是使用当前的名称按需计算。回答不错,但我不喜欢的一点是,你解释另一个人的切普纳答案,甚至连链接都没有。我保证没有人会费心向下滚动来找到你正在谈论的答案。我认为如果你把相关的代码复制到你的答案中,这将是一个很大的改进。毕竟,chepner并不是对琐碎的getter函数拥有独家版权。那么你的答案就100%完整了。@Aran Fey谢谢你的评论,也谢谢你指出遗漏的部分!我确实复制了他的代码,但只有两个单独的函数,我将进行更改以添加link.property是class,而不是内置函数。您的链接是正确的,但是链接的文本是不正确的。@LiuXiMin谢谢您的评论!我尊重我的回答。如果打开链接,网页标题会显示内置函数。我也同意属性本身是一个类,但在本文中,我将它描述为一个内置函数。@UdonN00dle好的,这不是一个大问题。Python中的Callable对象毕竟是一个类似的函数:-答案不错,但我不喜欢的一件事是,你在解释另一个人的切普纳答案时甚至没有链接到它。我保证没有人会费心向下滚动来找到你正在谈论的答案。我认为如果你把相关的代码复制到你的答案中,这将是一个很大的改进。毕竟,chepner并不是对琐碎的getter函数拥有独家版权。那么你的答案就100%完整了。@Aran Fey谢谢你的评论,也谢谢你指出遗漏的部分!我确实复制了他的代码,但只有两个单独的函数,我将进行更改以添加link.property是class,而不是内置函数。您的链接是正确的,但是链接的文本是不正确的。@LiuXiMin谢谢您的评论!我尊重我的回答。如果打开链接,网页标题会显示内置函数。我也同意财产是它的一个类别
elf,但在本文中,我将它描述为一个内置函数。@UdonN00dle好的,这不是一个大问题。Python中的可调用对象毕竟是一个类似的函数:-