Method Attribute Is Not Updating Itself Even Though I'm Clearly Assigning A Different Value To It
Solution 1:
In this example, self.email
is being assigned in the __init__
method of the class, which is only called when an instance of Email
is created. As such, when self.name
is reassigned, self.email
is not changed. To work around this, you can use a property
decorator:
classEmail:
def__init__(self, name):
self._name = name
self._email = f'{name}@hotmail.com'defdetails(self):
returnf'{self._name} | {self._email}' @propertydefname(self):
return self._name
@name.setterdefname(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())
Output:
James | James@hotmail.com
Michael | Michael@hotmail.com
Solution 2:
The simplest fix would be to make email
a property, rather than an attribute you set in __init__
.
classEmail:def__init__(self, name):
self.name = name
# self.email = self.name + "@hotmail.com"@propertydefemail(self):
return f'{self.name}@hotmail.com'defdetails(self):
return f'{self.name} | {self.email}'
Solution 3:
What went wrong in the OP?
If we open up the person
object right after you instantiated it with the line person = Email("James")
, it would be something like this:
person {
"name" : "James",
"email" : "James@hotmail.com"
}
If we update the name
variable in this person
object as you did with person.name = "Michael"
, and open up the person
object again, it would be:
person {
"name" : "Michael",
"email" : "James@hotmail.com"
}
Please note that at this stage, it is still the same person
object we instantiated earlier, and the email
variable is not changed from its previous state, because we didn't do anything about it, yet.
The answer posted by @chepner is very nice and clean, by setting email
field as a property
, and by setting it dynamically using the name
variable. Below is a copy of @chepner 's code:
classEmail:def__init__(self, name):
self.name = name
# self.email = self.name + "@hotmail.com"@propertydefemail(self):
return f'{self.name}@hotmail.com'defdetails(self):
return f'{self.name} | {self.email}'
What is property
and how is it used?
property
is a Python Built-in Function, a property
object has these methods:
getter
: used to get an attribute valuesetter
: used to set an attribute valuedeleter
: used to delete an attribute value
Now, what exactly is happening in @chepner 's answer? With the lines below, we are setting the email
as a property
:
@propertydefemail(self):
returnf'{self.name}@hotmail.com'
And this decorated function can also be used as a getter
, e.g. person.email
.
Note that in here we didn't link it to a variable (as shown in the Python documentation example), if we want / need, we can do so by replacing the return
statement and set an _email
variable in __init__
:
def__init__(self, input_name):
self._name = input_name
self._email = f'{self._name}@hotmail.com'@propertydefemail(self):
returnself._email
And then, as for the setter
and deleter
, we can create them as:
@email.setter
def email(self, input_email):
self._email = input_email
@email.deleter
def email(self):
del self._email
Note that the getter
, setter
, and deleter
methods all have the same name as the property
, just different decorators.
From the question description it is not needed to support updating the email address separately, but just following this example here, if we run person.email = "Michael@hotmail.com"
, because email
is a property
, it is triggering the setter
to set the value to the _email
variable.
Going back to the details
method in @chepner 's answer:
defdetails(self):
returnf'{self.name} | {self.email}'
By doing self.email
we are triggering the getter
to return the email address, which is dynamically generated in that return
statement return f'{self.name}@hotmail.com'
.
Solution 4:
As @Ajax1234 saying, the init function is calling when you create a new instance. Think it like a constructor if you are familiar with an object oriented language.
So, if you just change the person.name, you can change the name field but not the email variable which assigned with older value of name.
You have a few options about that case:
You can create a new Email object with name of Michael.
You can re-assign the e-mail directly, like you do in init function.
You can create a "setter" method for name like
setName(name)
and you can update the email in this function. So, when you call the setter, it automatically updates the email.
Post a Comment for "Method Attribute Is Not Updating Itself Even Though I'm Clearly Assigning A Different Value To It"