一、屬性(特性) 普通方法去執行的時候,後面需要加括弧,特性方法執行的時候和靜態欄位一樣不需要不需要加括弧. 特性方法不和欄位同名. 特性方法不能傳參數. 在我們定義資料庫欄位類的時候,往往需要對其中的類屬性做一些限制,一般用get和set方法來寫,那在python中,我們該怎麼做能夠少寫代碼,又能 ...
一、屬性(特性)
普通方法去執行的時候,後面需要加括弧,特性方法執行的時候和靜態欄位一樣不需要不需要加括弧.
特性方法不和欄位同名.
特性方法不能傳參數.
在我們定義資料庫欄位類的時候,往往需要對其中的類屬性做一些限制,一般用get和set方法來寫,那在python中,我們該怎麼做能夠少寫代碼,又能優雅的實現想要的限制,減少錯誤的發生呢,這時候就需要我們的@property.
獲取特性
class Foo: def __init__(self,name): self.name = name # 普通方法 def start(self): temp = '%s sb' %self.name return temp # 特性,將方法的執行方式變為和欄位一樣 @property def end(self): temp = '%s gd'%self.name return temp obj = Foo('alexsel') ret1 = obj.start() ret2 = obj.end print(ret2) print(obj.name) 輸出結果: alexsel gd alexsel
設置特性
設置特性方法的時候,所需要加的裝飾器名字規則是,你所設置特性方法名字點setter(例如:@end.setter)
class Foo: def __init__(self,name): self.name = name # 普通方法 def start(self): temp = '%s sb' %self.name return temp # 特性,將方法的執行方式變為和欄位一樣 @property def end(self): temp = '%s gd'%self.name return temp # 如果需要使用設置特性的的方法,就需要這個點前面名字和所要設置特性的方法同名,就像這裡的end @end.setter def end(self,value): print(value) self.name = value obj = Foo('alexsel') #獲取特性,獲取特性的時候,拿到的是@Property的返回值 ret2 = obj.end print(ret2) #設置特性,設置特性的時候,會執行@end.setter下麵的方法,這個'aaa'就傳遞給value obj.end = 'aaa' ret1 = obj.end print(ret1) 輸出結果: alexsel gd aaa aaa gd
這個特性在python中不是特別常用,因為我們一般可以使用普通的方法代替特性方法。
二、成員修飾符
首先介紹‘__’,這個在命名之前添加就會變成私有的,只有在類的內部才能訪問。
class Foo: book = 'alexsel' #命名的時候前面添加__,只有在類的內部才能訪問,在外部無法訪問 __book = 'book' def __init__(self): self.__name = 'alexsel' def start(self): print(Foo.__book) print(self.__name) def __end(self): print('__end') obj = Foo() print(obj.book) # print(obj.__book) #這種無法拿到欄位 #在外部也無法調用類私有方法 #obj.__end() #通過內部方法調用拿到欄位 obj.start() 輸出結果: alexsel book alexsel
私有的屬性只有自己可以訪問,當某個類繼承這個類之後,也無法訪問父類的私有屬性。
class Foo: book = 'alexsel' __book = 'book' def __init__(self): self.__name = 'alexsel' def start(self): print(Foo.__book) print(self.__name) self.__end() def __end(self): print('__end') class Bar(Foo): def start(self): print(self.__name)#子類繼承父類,也無法調用父類的私有屬性 obj = Bar() obj.start() 輸出結果: 報錯
靜態方法也是如此
class Foo: book = 'alexsel' __book = 'book' def __init__(self): self.__name = 'alexsel' def start(self): Foo.__add() #內部調用私有靜態方法 def __end(self): print('__end') @staticmethod def __add(): print('add') obj = Foo() obj.start() 輸出結果: add
python成員修飾符有兩種,一種是共有的,一種是私有的,共有的都可以訪問,私有的只有自己可以訪問,或者在外部間接訪問。
但是還有一種強行訪問私有屬性的方法,如下:
class Foo: book = 'alexsel' __book = 'book' def __init__(self): self.__name = 'alexsel' def start(self): Foo.__add() #內部調用私有靜態方法 def __end(self): print('__end') @staticmethod def __add(): print('add') obj = Foo() print(obj._Foo__book) 輸出結果: book
雖然可以使用,但是不推薦這種使用方法。
三、類的特殊成員
1.call
__call__()
的作用是使實例能夠像函數一樣被調用,同時不影響實例本身的生命周期(__call__()
不影響一個實例的構造和析構)。
__call__ 方法的執行是由對象後加括弧觸發的,即:對象() 或者 類()()。
class Foo: def __init__(self): print( Foo: def 'init') def __call__(self, *args, **kwargs): print('call') return 1 r = Foo() r() r = Foo()()#加第一個括弧執行__init__,執行完__init__,獲取到一個對象,對象加一個括弧就是執行__call__,拿到返回值 print(r) 輸出結果: init call init call 1
類後面添加括弧執行__init__方法,對象後面加括弧執行__call__方法。
2.getitem,setitem,delitem
用於索引操作,如字典。以上分別表示獲取、設置、刪除數據。
首先得實例是字典類型的操作。
class Foo: def __init__(self): print('init') def __call__(self, *args, **kwargs): print('call') return 1 def __getitem__(self, item): print(item) def __setitem__(self, key, value): print(key,value) def __delitem__(self, key): print(key) r = Foo() r() #調用__call__方法 r['k1']#使用中括弧傳參數的時候,預設使用過的是__getitem__方法 r['xxx'] = 123#這裡的xxx傳給__setiem__的key,123傳給__setitem__的value。 del r['xxx'] #刪除的時候,調用的是__delitem__方法 輸出結果: init call k1
接下來是切片類型的操作,在切片操作的時候,在2.x版本中,執行的是__getslice_,__setslice__,delslice__方法,在3.x中的版本執行的是還是__getitem__,__setitem__,__delitem__方法。
class Foo: def __init__(self): print('init') def __call__(self, *args, **kwargs): print('call') return 1 def __getitem__(self, item): print(item,type(item),'__getitem__') def __setitem__(self, key, value): print(key,value) def __delitem__(self, key): print(key) r = Foo() #使用切片的時候,在2.x版本中,調用的是__getslice__方法,在3.x中調用的是__getitem__方法。 r[1:3] r[1:3] = [11,22,33] #這裡執行__setitem__方法 del r[1:3] #在這裡執行__delitem__方法
3.dict
dict是用來存儲對象屬性的一個字典,其鍵為屬性名,值為屬性的值。
class Foo: """ 我是一個註釋 """ book = 'alexsel' __book = 'book' def __init__(self): self.__name = 'alexsel' def start(self): Foo.__add() #內部調用私有靜態方法 def __end(self): print('__end') @staticmethod def __add(): print('add') obj = Foo() print(obj.__dict__) #獲取對象裡面所有欄位 print(Foo.__dict__) 輸出結果: {'_Foo__name': 'alexsel'} {'book': 'alexsel', '_Foo__book': 'book', '__init__': <function Foo.__init__ at 0x00000000027CF950>, '__dict__': <attribute '__dict__' of 'Foo' objects>, 'start': <function Foo.start at 0x00000000027EBB70>, '_Foo__add': <staticmethod object at 0x00000000027B6390>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '_Foo__end': <function Foo.__end at 0x00000000027EBBF8>, '__doc__': '\n 我是一個註釋\n ', '__module__': '__main__'}
4.__iter__
類的迭代器可以使用for迴圈迭代類。
如果創建的對象可以被迭代,在類的內部就執行了__iter__方法。
class Foo: def __iter__(self): yield 1 yield 2 yield 3 yield 4 obj = Foo() #如果執行for對象時,自動會執行對象的iter方法 for i in obj: print(i) 輸出結果: 1 2 3 4