python類方法靜態方法
A. python中的面向對象(進階)
一、實例方法,類方法,靜態方法
我們首先寫一個類,裡麵包含這三種方法。
可以看到,我們用到了兩個裝飾器。
我們用類和實例分別調用下類方法
我們用類和實例分別調用下靜態方法
靜態方法其實就是把一個普通的函數寫在類里,與直接在外層寫一個函數是一樣的,本質上是一個函數。
為了方便理解,我們分別列印下這些方法的類型
通過type()查看對象是方法還是函數
此外,還可以通過inspect模塊判斷某個對象是否是某種類型,返回布爾值。
用法
小Tips:概念理解
直接def定義的,我們叫做函數
把函數放到類里,我們叫做方法
方法可以通過裝飾器staticmethod轉為(放在方法里的)函數
繼承
一個類繼承另一個類時,會自動獲得另一個類的所有屬性和方法,被繼承的類稱之為父類,新類稱為子類。子類擁有父類所有的屬性和方法,並且可以定義自己的屬性和方法
我們以上邊的Rectangle類為父類來試一下
1)完全繼承
可以看到,子類完全繼承父類後,可以直接調用父類的所有方法。
2)部分繼承
部分繼承:繼承父類後,修改父類的同名方法
我們試一下,Square繼承Rectangle後,修改__init__()方法
3)拓展父類的方法
在保留父類中某個方法的代碼同時,對方法進行拓展
可以在方法中加入"super().方法名"來實現
4)@property
B. python類方法和靜態方法有什麼用
主要特點就是需要綁定到一個對象上,python解析器會自動把實例自身傳遞給方法,如14行所示,而直接使用InstanceMethod.f1()調用方法是不行的。
class InstanceMethod(object):
def __init__(self, a):
self.a = a
def f1(self):
print 'This is {0}.'.format(self)
def f2(self, a):
print 'Value:{0}'.format(a)
if __name__ == '__main__':
# im = InstanceMethod()
im = InstanceMethod('233')
im.f1()
# im.f2()
im.f2(233)
C. python 靜態方法可以訪問類方法嗎
Python的靜態方法和類成員方法都可以被類或實例訪問,兩者概念不容易理清,但還是有區別的:
1)靜態方法無需傳入self參數,類成員方法需傳入代表本類的cls參數;
2)從第1條,靜態方法是無法訪問實例變數的,而類成員方法也同樣無法訪問實例變數,但可以訪問類變數;
3)靜態方法有點像函數工具庫的作用,而類成員方法則更接近類似Java面向對象概念中的靜態方法。
實現靜態方法和類方法的兩種方式
一、在Python 2.3及之前,用staticmethod和classmethod類型對象包裝實現
例子如下(注意print里的說明):
class MyClass:
val1 = 'Value 1'
def __init__(self):
self.val2 = 'Value 2'
def staticmd():
print '靜態方法,無法訪問val1和val2'
smd = staticmethod(staticmd)
def classmd(cls):
print '類方法,類:' + str(cls) + ',val1:' + cls.val1 + ',無法訪問val2的值'
cmd = classmethod(classmd)
執行:
>>> mc = MyClass()
>>> mc.smd()
>>> mc.cmd()
>>> MyClass.smd()
>>> MyClass.cmd()
二、在Python 2.4及之後,用裝飾器(decorators)實現
裝飾器使用@操作符,例子如下:
class MyClass:
val1 = 'Value 1'
def __init__(self):
self.val2 = 'Value 2'
@staticmethod
def staticmd():
print '靜態方法,無法訪問val1和val2'
@classmethod
def classmd(cls):
print '類方法,類:' + str(cls) + ',val1:' + cls.val1 + ',無法訪問val2的值'
D. Python 中的 classmethod 和 staticmethod 有什麼具體用途
classmethod:類方法
staticmethod:靜態方法
在python中,靜態方法和類方法都是可以通過類對象和類對象實例訪問。但是區別是:
@classmethod 是一個函數修飾符,它表示接下來的是一個類方法,而對於平常我們見到的則叫做實例方法。類方法的第一個參數cls,而實例方法的第一個參數是self,表示該類的一個實例。
普通對象方法至少需要一個self參數,代表類對象實例
類方法有類變數cls傳入,從而可以用cls做一些相關的處理。並且有子類繼承時,調用該類方法時,傳入的類變數cls是子類,而非父類。對於類方法,可以通過類來調用,就像C.f(),有點類似C++中的靜態方法, 也可以通過類的一個實例來調用,就像C().f(),這里C(),寫成這樣之後它就是類的一個實例了。
靜態方法則沒有,它基本上跟一個全局函數相同,一般來說用的很少
Example 1:
>>>classa():
@staticmethod
defstaticm():
print'static'
defnormalm(self):
print'nomarl',self
@classmethod
defclassm(cls):
print'class',cls
>>>a1=a()
>>>a1.normalm()
nomarl<__main__.ainstanceat0x84dddec>
>>>a1.staticm()
static
>>>a1.classm()
class__main__.a
>>>type(a)
<type'classobj'>
>>>type(a1)
<type'instance'>
Example 2:
classA(object):
@classmethod
defcm(cls):
print'類方法cm(cls)調用者:',cls.__name__
@staticmethod
defsm():
print'靜態方法sm()被調用'
classB(A):
pass
A.cm()
B.cm()
A.sm()
B.sm()
輸出:
類方法cm(cls)調用者:A
類方法cm(cls)調用者:B
靜態方法sm()被調用
靜態方法sm()被調用
@classmethod與@staticmethod的應用實例
#!/usr/bin/envpython
#-*-coding:utf-8-*-
classTClassStatic(object):
obj_num=0
def__init__(self,data):
self.data=data
TClassStatic.obj_num+=1
defprintself(self):
print("self.data:",self.data)
@staticmethod
defsmethod():
print("thenumberofobjis:",TClassStatic.obj_num)
@classmethod
defcmethod(cls):
print("cmethod:",cls.obj_num)
cls.smethod()
defmain():
objA=TClassStatic(10)
objB=TClassStatic(12)
objB.printself()
objA.smethod()
objB.cmethod()
print("------------------------------")
TClassStatic.smethod()
TClassStatic.cmethod()
if__name__=="__main__":
main()
輸出結果如下:
('self.data:',12)
('thenumberofobjis:',2)
('cmethod:',2)
('thenumberofobjis:',2)
------------------------------
('thenumberofobjis:',2)
('cmethod:',2)
('thenumberofobjis:',2)
E. python類方法和靜態方法的區別
類方法,可以調用類屬性。。。用於操作一些類中的公有屬性。。。比如這個士兵類,每個士兵都擁有一把相同的槍(gun),都有相同的最大血量(maxhp),如果在創建對象的時候,一個一個的賦值,就會顯得比較多餘。。。因此,把這兩個屬性提出來,作為一個公有屬性。。即每個士兵對象,都擁有一把95式步槍,都擁有30的最大血量。。之後聲明一個類方法(public),之後可以在類方法中,針對這兩個公有的屬性進行操作。。。
靜態方法,其實更像一個與類幾乎無關的函數。。不能操作類中的任何屬性。。所以它並不是用來操作類與對象本身的。。。但它又可以被對象調用。。。。比如游戲中,與士兵對話,士兵說話的內容一般存在資料庫中。。而當主角與士兵對話,針對資料庫查詢,並輸出到UI界面的相關工作,就可以放在這個函數里。。這樣會讓代碼結構更清晰。。。當然,如果不嫌亂,寫在類方法中,也是可以的。。。有人覺得PYTHON的靜態方法是雞肋。。它也確實不是必須的,但有時候卻可以讓代碼結構更清晰。。。比如你有幾十種不同的士兵類,你要找到對應每一個類的數據操作相關的函數,就會顯得很困難。。。適當使用靜態方法,就顯得一目瞭然