夏天到,裝飾器讓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驚呆了,說:你,你竟然刪除了我…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章