天天看點

夏天到,裝飾器讓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 操作