微信公眾號:碼農充電站pro
個人主頁:https://codeshellme.github.io
與客戶保持良好的關係可以使生產率加倍。
—— Larry Bernstain
目錄
類中的變數稱為屬性
,類中的函式稱為方法
。
類中的屬性分為:
- 例項屬性:物件所有,互不干擾
- 類屬性:類所有,所有物件共享
類中的方法分為:
- 例項方法:定義中有
self
引數 - 類方法:定義中有
cls
引數,使用@classmethod
裝飾器 - 靜態方法:定義中即沒有
self
引數,也沒有cls
引數,使用@staticmethod
裝飾器
1,例項屬性與類屬性
類的物件,就是類的一個例項。類的例項屬性
被物件所有,包含在每個物件之中,不同的物件之間,互不干擾。類的類屬性
被類所有,被包含在類中,是所有的類物件
共享。
一般情況下,例項屬性會在__init__
方法中宣告並初始化,並且使用self
來繫結。而類屬性是在類作用域中被宣告,並且不使用self
來繫結。
例如下面程式碼中,country
為類屬性,__name
為例項屬性:
#! /usr/bin/env python3
class People:
country = 'china'
def __init__(self, name):
self.__name = name
訪問例項屬性時使用物件.屬性名
的格式,例項屬性屬於物件各自的,互不影響:
>>> p1 = People('小明')
>>> p2 = People('小美')
>>>
>>> p1.get_name()
'小明'
>>> p2.get_name()
'小美'
類屬性被所有物件共有,一旦被改變,所有物件獲取到的值都會被改變。訪問類屬性時使用類名.屬性名
的格式,也可以使用物件.屬性名
的格式來訪問:
>>> People.country # 用`類名.屬性名`的格式訪問
'CHINA'
>>> p1.country # 用`物件.屬性名`的格式訪問
'china'
>>> p2.country
'china'
>>>
>>> People.country = 'CHINA' # 類屬性的值被改變
>>> p1.country # 每個物件獲取到的值也會被改變
'CHINA'
>>> p2.country
'CHINA'
注意,在使用物件.屬性名
的格式訪問物件時,不要以這種格式對類屬性
進行賦值,否則結果可能不會像你想象的一樣:
>>> p1 = People('小明')
>>> p2 = People('小美')
>>> People.country
'china'
>>> p1.country
'china'
>>> p2.country
'china'
>>> p1.country = '中國' # 使用`物件.屬性名`的格式對類物件進行賦值
>>> p1.country # 只有 p1.country 被改變
'中國'
>>> p2.country # p2.country 沒有被改變
'china'
>>> People.country # People.country 也沒有被改變
'china'
從上面程式碼中可以看到,在Python 中以物件.屬性名
格式對類屬性
進行賦值時,只有p1.country
的值被改變了,p2.country
和 People.country
的值都沒有被改變。
實際上,這種情況下,類屬性
的值並沒有被改變,而是物件p1
中多了一個country
例項屬性,此後,p1.country
訪問的是p1
的例項屬性,p1.country
對屬性country
的訪問遮蔽了類中的country
屬性,而p2.country
和 People.country
訪問的依然是原來的類屬性
。
所以,類名.屬性名
和物件.屬性名
的格式都可以訪問類屬性
的值,但儘量避免使用物件.屬性名
的格式對類屬性的值進行賦值,否則可能會發生混亂。
建議:
不管是訪問還是改變
類屬性
的值,都只用類名.屬性名
的格式
2,例項方法,類方法,靜態方法
Python 類中有三種方法:
- 例項方法
- 類方法
- 靜態方法
例項方法
屬於物件,方法中都有一個self
引數(代表物件本身)。例項方法只能由物件呼叫,不能通過類名訪問。例項方法中可以訪問例項屬性和類屬性。
類方法
屬於類,方法中都有一個cls
引數(代表類本身)。類方法即可以通過類名訪問,也可以通過物件訪問,類方法中只能訪問類屬性,不能訪問例項屬性。
注意:
Python 直譯器在構造類與物件時,
類
是先於物件
產生的。因此,
類屬性與類方法
是先於例項屬性與例項方法
產生的。所以當類方法產生時,還沒有例項屬性,因此,類方法中不能訪問例項屬性。
靜態方法
中,沒有self
引數,也沒有cls
引數。因此,在靜態方法中,即不能訪問類屬性
,也不能訪問例項屬性
。靜態方法可以使用類名訪問,也可以使用物件訪問。
在Python 中,定義類方法需要用到裝飾器@classmethod
,定義靜態方法需要用到裝飾器@staticmethod
。
例項方法演示
#! /usr/bin/env python3
class People:
country = 'china'
def __init__(self, name):
self.__name = name
# 例項方法中有self 引數
def instance_method_test(self):
# 在例項方法中訪問了例項屬性和類屬性
print('name:%s country:%s' % (self.__name, People.country))
使用:
>>> p = People('小明')
>>> p.instance_method_test()
name:小明 country:china
在例項方法中訪問了例項屬性__name
和類屬性country
,均可以被訪問。
類方法演示
#! /usr/bin/env python3
class People:
country = 'china'
def __init__(self, name):
self.__name = name
# 類方法中都有cls 引數
@classmethod
def class_method_test1(cls):
print('在類方法中訪問類屬性country:%s' % cls.country)
@classmethod
def class_method_test2(cls):
print('在類方法中訪問例項屬性__name:%s' % self.__name)
使用:
>>> p = People('小明')
>>> p.class_method_test1() # 在類方法中訪問類屬性,可以
在類方法中訪問類屬性country:china
>>>
>>> p.class_method_test2() # 在類方法中訪問例項屬性,出現異常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/wp/to_beijing/People.py", line 18, in class_method_test2
print('在類方法中訪問例項屬性__name:%s' % self.__name)
NameError: name 'self' is not defined
從上面程式碼中可以看到,在類方法中可以訪問類屬性,但在類方法中訪問例項屬性,會出現異常。
靜態方法演示
#! /usr/bin/env python3
class People:
country = 'china'
def __init__(self, name):
self.__name = name
# 靜態方法中即沒有self 引數也不沒有cls 引數
@staticmethod
def static_method_test1():
print('在靜態方法中訪問類屬性country:%s' % cls.country)
@staticmethod
def static_method_test2():
print('在靜態方法中訪問例項屬性__name:%s' % self.__name)
使用:
>>> p = People('小明')
>>> p.static_method_test1() # 在靜態方法中訪問類屬性,出現異常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/wp/to_beijing/People.py", line 14, in static_method_test1
print('在靜態方法中訪問類屬性country:%s' % cls.country)
NameError: name 'cls' is not defined
>>>
>>> p.static_method_test2() # 在靜態方法中訪問例項屬性,出現異常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/wp/to_beijing/People.py", line 18, in static_method_test2
print('在靜態方法中訪問例項屬性__name:%s' % self.__name)
NameError: name 'self' is not defined
從上面程式碼中可以看到,在靜態方法中無論訪問例項方法還是類方法,都會出現異常。
3,專有方法
我們之前講到過的魔法方法
,即以雙下劃線__
開頭且結尾的方法__xxx__
,就是專有方法
。這些方法都被Python 賦予了特殊的含義,使用者可以根據需要,來實現這些方法。
下面我們介紹一些 Python 中常見的專有方法。
__len__
方法
實現該方法的類的物件,可以用len()
函式計算其長度。
__str__
方法
實現該方法的類的物件,可以轉化為字串。
__call__
方法
實現該方法的類的物件,可以像函式一樣呼叫。
__iter__
方法
實現該方法的類的物件,是可迭代的。
__setitem__
方法
實現該方法的類的物件,可以用索引
的方式進行賦值。
__getitem__
方法
實現該方法的類的物件,可以用索引
的方式進行訪問。
__contains__
方法
實現該方法的類的物件,可以進行in
運算。
__add__
方法
實現該方法的類的物件,可以進行加+
運算。
__sub__
方法
實現該方法的類的物件,可以進行減-
運算。
__mul__
方法
實現該方法的類的物件,可以進行乘*
運算。
__div__
方法
實現該方法的類的物件,可以進行除/
運算。
__pow__
方法
實現該方法的類的物件,可以進行乘方
運算。
__mod__
方法
實現該方法的類的物件,可以進行取模
運算。
__eq__
方法
實現該方法的類的物件,可以進行相等==
比較。
__ne__
方法
實現該方法的類的物件,可以進行不等於!=
比較。
__gt__
方法
實現該方法的類的物件,可以進行大於>
比較。
__ge__
方法
實現該方法的類的物件,可以進行大於等於>=
比較。
__lt__
方法
實現該方法的類的物件,可以進行小於<
比較。
__le__
方法
實現該方法的類的物件,可以進行小於等於<=
比較。
(完。)
推薦閱讀:
Python 簡明教程 --- 16,Python 高階函式
Python 簡明教程 --- 17,Python 模組與包
Python 簡明教程 --- 18,Python 物件導向
Python 簡明教程 --- 19,Python 類與物件
歡迎關注作者公眾號,獲取更多技術乾貨。