天天看点

夏天到,装饰器让Python秀出性感属性:Property+Decorators+-+Getters,+Setters,+and+Deleters

John Smith曾经是我的好基友,没有之一,今天我们拿他做个试验:

初始代码,我们做一个打印员工John Smith信息的类,实例emp_1会用类属性输出:

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
        self.email = first + "." + last + '@email.com'
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
emp_1 = Employee('John', 'Smith')

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname())
           
John
[email protected]
John Smith
           

下面,当我们在类外修改了实例emp_1的属性,那么实例属性输出也改变;不过,你会发现问题,员工的first name和last name被改变了,但是,email却没有自动跟着改变。

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
        self.email = first + "." + last + '@email.com'
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
emp_1 = Employee('John', 'Smith')

#New edit
emp_1.first = 'Jim' 

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname())
           
Jim
[email protected]
Jim Smith
           

Anyway,我还是想让email自动改变,在Python中该怎么办呢?

我们可以定义一个函数输出;不过你会发现,你需要一个讨厌的括号才能像刚才一样去调出email。

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
#         self.email = first + "." + last + '@email.com'
    def email(self):
        return '{}.{}@email.com'.format(self.first, self.last)

    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
emp_1 = Employee('John', 'Smith')

#New edit
emp_1.first = 'Jim' 

print(emp_1.first)
print(emp_1.email())
print(emp_1.fullname())
           
Jim
[email protected]
Jim Smith
           

当我们还是想像调用属性一样来调用函数return结果,这时候,一个叫做property的装饰器说它可以解决完美主意者的烦恼;当然,当fullname发现这个技巧时候,它也果断跟进了一个@property,并脱掉了它的括号,因为这样很性感,特别是在一个完美的夏天。

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
#         self.email = first + "." + last + '@email.com'
    @property
    def email(self):
        return '{}.{}@email.com'.format(self.first, self.last)
    @property
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
emp_1 = Employee('John', 'Smith')

#New edit
emp_1.first = 'Jim' 

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname)
           
Jim
[email protected]
Jim Smith
           

于是,John很兴奋,因为其实他想改名很久了,他直接来了个:

emp_1.email = ‘[email protected]’

emp_1.fullname = ‘Lady GaGa’

可是,结果脱掉外套后的他,摔了一个大跟头:AttributeError: can’t set attribute

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
#         self.email = first + "." + last + '@email.com'
    @property
    def email(self):
        return '{}.{}@email.com'.format(self.first, self.last)
    @property
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
emp_1 = Employee('John', 'Smith')

emp_1.email = '[email protected]'
emp_1.fullname = 'Lady GaGa'

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname)
           
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-43-05f72f854431> in <module>()
     13 emp_1 = Employee('John', 'Smith')
     14 
---> 15 emp_1.email = '[email protected]'
     16 emp_1.fullname = 'Lady GaGa'
     17 


AttributeError: can't set attribute
           

这时候,property说话了,它说:除了帮你脱掉外套,我还可以做更多…

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
    @property
    def email(self):
        return '{}.{}@email.com'.format(self.first, self.last)
    @property
    def fullname(self):
        return '{} {}'.format(self.first, self.last)  
    @fullname.setter
    def fullname(self, name):
        first, last = name.split(' ')
                # fullname的定义方式为emp_1.fullname = 'Lady Gaga',所以split一下
        self.first = first
        self.last = last  
emp_1 = Employee('John', 'Smith')
emp_1.fullname = 'Lady Gaga'

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname)
           
Lady
[email protected]
Lady Gaga
           

Jonh问:你为什么不早说?竟然有这种神操作,我不想活了。property说:如此需求,我也可以帮你实现:

class Employee:
    def __init__(self, first, last):
        self.first = first
        self.last = last
    @property
    def email(self):
        return '{}.{}@email.com'.format(self.first, self.last)
    @property
    def fullname(self):
        return '{} {}'.format(self.first, self.last)
    
    @fullname.setter
    def fullname(self, name):
        first, last = name.split(' ')
                # fullname的定义方式为emp_1.fullname = 'Lady Gaga',所以split一下
        self.first = first
        self.last = last
    @fullname.deleter
    def fullname(self):
        print("Gandiao Name")
        self.first = None
        self.last = None
    
emp_1 = Employee('John', 'Smith')

emp_1.fullname = 'Lady Gaga'

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname)

print("before deleter")
del emp_1.fullname
print("after deleter")

print(emp_1.first)
print(emp_1.email)
print(emp_1.fullname)
           
Lady
[email protected]
Lady Gaga
before deleter
Gandiao Name
after deleter
None
[email protected]
None None
           

Jonh惊呆了,说:你,你竟然删除了我…

夏天到,装饰器让Python秀出性感属性:Property+Decorators+-+Getters,+Setters,+and+Deleters
下一篇: File 操作