簡介
類的成員
python中類的成員可以分為三大類:字段捅伤、方法和屬性
類的方法
包括:普通方法、靜態(tài)方法和類方法巫玻,三種方法在內(nèi)存中都?xì)w屬于類丛忆,區(qū)別在于調(diào)用方式不同
- 普通方法:由對象調(diào)用祠汇;至少一個(gè)self參數(shù);執(zhí)行普通方法時(shí)熄诡,自動將調(diào)用該方法的對象賦值給self可很;
- 類方法:由類調(diào)用; 至少一個(gè)cls參數(shù)凰浮;執(zhí)行類方法時(shí)根穷,自動將調(diào)用該方法的類復(fù)制給cls;
- 靜態(tài)方法:由類調(diào)用导坟;無默認(rèn)參數(shù)屿良;
三者相同點(diǎn):對于所有的方法而言,均屬于類(非對象)中惫周,所以尘惧,在內(nèi)存中也只保存一份
三者不同點(diǎn):方法調(diào)用者不同、調(diào)用方法時(shí)自動傳入的參數(shù)不同
普通方法是最常見的方法递递,大家都比較熟悉喷橙。本文要討論的是類方法和靜態(tài)方法
定義和調(diào)用
定義
class Foo():
def __init__(self, name):
self.name = name
def bar(self):
"""
定義普通方法:至少需要一個(gè)參數(shù)self
"""
print('Hello,{}'.format(self.name))
@classmethod
def class_foo(cls, x):
"""
定義類方法:至少需要一個(gè)cls參數(shù)
"""
print('Executing class_foo({}, {})'.format(cls, x))
@staticmethod
def static_foo(x):
"""
定義靜態(tài)方法:無默認(rèn)參數(shù)
"""
print('Executing static_foo({})'.format(x))
在定義上靜態(tài)方法staticmethod和類方法classmethod需要分別使用裝飾器@staticmethod登舞、@classmethod
調(diào)用
普通方法在調(diào)用之前需要先對類進(jìn)行實(shí)例化贰逾。調(diào)用方法:實(shí)例名.方法名()
In [2]: foo = Foo('bar')
In [3]: foo.bar()
Hello,bar
類方法可直接使用類名.方法名()調(diào)用。調(diào)用方法:類名.方法名()或者實(shí)例名.方法名()
In [4]: foo.class_foo(1)
Executing class_foo(<class '__main__.Foo'>菠秒, 1)
In [5]: Foo.class_foo(1)
Executing class_foo(<class '__main__.Foo'>疙剑, 1)
靜態(tài)方法的也可直接使用類名.方法名()調(diào)用。調(diào)用方法:類名.方法名()或者實(shí)例名.方法名()
In [6]: foo.static_foo(1)
Executing static_foo(1)
In [7]: Foo.static_foo(1)
Executing static_foo(1)
兩者的不同
@classmethod
如果我們想創(chuàng)建一個(gè)在類中(而不是在實(shí)例中)運(yùn)行的方法践叠,我們可以這樣做:
def iget_no_of_instance(ins_obj):
return ins_obj.__class__.no_inst
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print iget_no_of_instance(ik1)
在Python2.2以后可以使用@classmethod裝飾器來創(chuàng)建類方法.
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
@classmethod
def get_no_of_instance(cls_obj):
return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()
使用@classmethod的好處是:無論我們是從類中還是從實(shí)例中調(diào)用方法言缤,都會將類傳給第一個(gè)參數(shù)。
@staticmethod
我們經(jīng)常需要用到一些和類有關(guān)的功能禁灼,但又無需類或?qū)嵗齾⑴c——例如如設(shè)置環(huán)境變量管挟,改變另外一個(gè)類的屬性等。在這些情況下弄捕,我們也可以直接使用函數(shù)僻孝,但這樣做的話會將相關(guān)的代碼塊分開,導(dǎo)致后期的維護(hù)問題守谓。
簡單的例子如下:
def checkind():
return (IND == 'ON')
class Kls(object):
def __init__(self,data):
self.data = data
def do_reset(self):
if checkind():
print('Reset done for:', self.data)
def set_db(self):
if checkind():
self.db = 'new db connection'
print('DB connection made for:',self.data)
得到的輸出:
Reset done for: 12
DB connection made for: 12
如果我們使用@staticmethod穿铆,我們可以將所有代碼放在同一個(gè)代碼塊里:
IND = 'ON'
class Kls(object):
def __init__(self, data):
self.data = data
@staticmethod
def checkind():
return (IND == 'ON')
def do_reset(self):
if self.checkind():
print('Reset done for:', self.data)
def set_db(self):
if self.checkind():
self.db = 'New db connection'
print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()
輸出:
Reset done for: 12
DB connection made for: 12