1. 程式人生 > >Python __slots__限制動態添加變量

Python __slots__限制動態添加變量

異常 manager 實現 獲取 方法 add ini 破壞 bob

Python是一種非常靈活的動態語言,有時感覺太靈活以至於不知道遵循什麽樣的規則去駕馭。不過Python已經是非常完備的語言,想實現什麽樣的功能都是有方法的,而且也很容易,比如限制一個類動態添加成員變量。

一般情況下,我們定義完一個類,如果不加任何限制,還可以動態地為該類的對象或該類添加成員變量。

 1 class Employee:
 2     def __init__(self,name=‘‘):
 3         self.name = name
 4 
 5 if __name__ == "__main__":
 6     try:
 7         employee1 = Employee(
Bob) 8 #動態為一個對象添加成員變量 9 employee1.tel = 11111111 10 print(employee1.name,employee1.tel) 11 employee2 = Employee(Tom) 12 #employee2對象沒有tel成員變量 13 print(employee2.name,employee2.tel) 14 except AttributeError as e: 15 print(e) 16 #動態為一個類添加成員變量
17 Employee.tel = [] 18 print(employee2.name,employee2.tel) 19 20 #Bob 11111111 21 #‘Employee‘ object has no attribute ‘tel‘ 22 #Tom []

看起來很方便,不過如果我們如果不想使用者破壞類的結構、隨便添加成員變量,要怎麽做呢?

答案是,可以使用__slots__對象。

在類中,__slots__是一個以元組形式被定義的,只有在元組裏的屬性,才可以被賦值,不在元組裏的屬性賦值時會報錯。

 1 class Employee:
 2     __slots__
= (name) 3 def __init__(self,name=‘‘): 4 self.name = name 5 6 if __name__ == "__main__": 7 employee1 = Employee(Bob) 8 #動態為一個對象添加成員變量,但不在__slots__定義的元組內,會報異常 9 employee1.tel = 11111111 10 print(employee1.name,employee1.tel) 11 12 #AttributeError: ‘Employee‘ object has no attribute ‘tel‘

__solts__不能被子類繼續,如果想限制子類的成員變量,子類也要定義__slots__變量,同時會繼承父類的__slots__

 1 class Employee:
 2     __slots__ = (name)
 3     def __init__(self,name=‘‘):
 4         self.name = name
 5 
 6 class Manager1(Employee):
 7     pass
 8 class Manager2(Employee):
 9     __slots__ = (addr)
10 
11 if __name__ == "__main__":
12     manager1 = Manager1(Bill)
13     #動態為一個對象添加成員變量
14     manager1.tel = 22222222
15     print(manager1.name,manager1.tel)
16     manager2 = Manager2()
17     manager2.name = David
18     manager2.addr = BJ
19     print(manager2.name,manager2.addr)
20     #動態為一個對象添加成員變量,不在__slots__裏,會報異常
21     manager2.tel = 33333333
22     print(manager2.tel)
23 
24 #Bill 22222222
25 #David BJ
26 #AttributeError: ‘Manager2‘ object has no attribute ‘tel‘

如果想進一步限制對成員變量的使用,可以重載__setattr__, __getattr__,__getattribute__函數,__setattr__函數可以在賦值前攔截;__getattr__在找不到屬性時被調用;__getattribute__則在獲取屬性值時無條件被調用,同時__getattr__不再被調用。註意不要在__getattribute__裏使用self.attr來訪問變量,這會導致無限遞歸循環。

class Employee:
    __slots__ = (name)
    def __init__(self,name=‘‘):
        self.name = name

class Manager2(Employee):
    __slots__ = (addr)
    def __setattr__(self,name,value):
        if name == tel:
            raise AttributeError(manager has no tel)
        object.__setattr__(self, name, value)
    def __getattr__(self,name):
        if name == tel:
            return 0
        object.__getattribute__(self, name)
if __name__ == "__main__":
    manager2 = Manager2(Jone)
    manager2.name = David
    manager2.addr = BJ
    try:
        manager2.tel = 11111111
    except Exception as e:
        print(e)
    print(manager2.name,manager2.addr,manager2.tel)

#manager has no tel
#David BJ 0

參考資料:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200605560b1bd3c660bf494282ede59fee17e781000

https://www.cnblogs.com/rainfd/p/slots.html

Python __slots__限制動態添加變量