简体   繁体   English

在 setter 和 @property 装饰器中遇到一些麻烦和混乱,并非所有在 `__init__` 中定义的属性都已更新

[英]having some trouble and confusion in setter & @property decorator, not all attributes defined in `__init__` are updated

class Employee:
    def __init__(self,first,last,pay):
        self.first = first
        self.last = last
        self.pay = pay
        self.annual_pay = 12*pay
        self.email = self.first + '.' + self.last + '@email.com'

    @property                   
    def fullname(self):
        return ('{} {}'.format(self.first,self.last))

    @fullname.setter            
    def fullname(self,name):
        first,last = name.split(' ')
        self.first = first
        self.last = last

emp1 = Employee('test1','subject1',10000)
emp1.fullname='test2 subject2'
print(emp1.fullname)
print(emp1.email)

I used setter to assign user a fullname() and override the attributes set by init already on the top, but in the output it only changed fullname as test2 subject2 meanwhile email had been unchanged as test1.subject1@email.com (i learned from a tutorial and i thought we can override default attributes by this setter functionality) (Also that guy didn't use email in init like I did but instead he had a separate function for it with @property decorater with it) I used setter to assign user a fullname() and override the attributes set by init already on the top, but in the output it only changed fullname as test2 subject2 meanwhile email had been unchanged as test1.subject1@email.com (i learned from一个教程,我认为我们可以通过这个设置器功能覆盖默认属性)(另外那个家伙没有像我一样在init中使用 email 而是他有一个单独的 function 和 @property 装饰器)

That is because the value of email was computed and saved when you ran __init__() .这是因为 email 的值是在您运行__init__()时计算并保存的。 Just because you change self.first and self.last doesn't mean self.email will be affected, because it is not saved in terms of its relationship to those variables.仅仅因为您更改self.firstself.last并不意味着self.email会受到影响,因为它不会根据与这些变量的关系进行保存。 It is saved as a string.它被保存为一个字符串。

Example:例子:

a = "hello"
b = "world"
c = a + b
a = "goodbye"
print(c)
>>> "hello world"

Here, c was set to a+b and that value was saved when that line was executed.在这里, c被设置为a+b并且该值在该行执行时被保存。 Changing a after we have already given c its value won't change it.在我们已经a c之后更改它的值不会改变它。 It is already set, and we would have to do c = a+b again to get it to print out goodbye world .它已经设置好了,我们必须再次执行c = a+b才能打印出goodbye world

In your case, you'd have to modify it in the setter:在您的情况下,您必须在设置器中对其进行修改:

@fullname.setter            
def fullname(self,name):
    first,last = name.split(' ')
    self.first = first
    self.last = last
    self.email = self.first + '.' + self.last + '@email.com'

However that is not good practice, as the setter should only change the specific variable you're accessing.然而,这不是一个好的做法,因为 setter 应该只更改您正在访问的特定变量。 That is why the tutorial you were reading had a function for email: If you want the it to be dynamically computed based on whatever the values of first and last are at the moment you check it, you should always use a function:这就是为什么您正在阅读的教程有 email 的 function:如果您希望根据您检查时firstlast的值动态计算它,您应该始终使用 ZC1C425268E68394F14Z074E68394F14AB7

def email(self):
    return self.first + '.' + self.last + '@email.com'

print(emp1.email())

If you want, you can use theproperty decorator like the tutorial does:如果你愿意,你可以像教程一样使用property装饰器:

@property
def email(self):
    return self.first + '.' + self.last + '@email.com'

This is just syntactical sugar to allow you to call it as before:这只是语法糖,让您可以像以前一样调用它:

print(emp1.email)

Instead of having to call it like a function, even though that is all it is.不必像 function 那样称呼它,尽管仅此而已。

As a sidenote, I'd recommend using string formatting , which is generally preferred to using + to join strings together in cases like this:作为旁注,我建议使用string formatting ,在这种情况下,通常首选使用+将字符串连接在一起:

return f"{self.first}.{self.last}@email.com"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM