實例方法:
顧名思義就是給實例使用的方法抡笼。
就是我們使用最普遍的在類內(nèi)部定義的方法。
實例方法第一個參數(shù)為 self黄鳍。self表示當(dāng)前調(diào)用此方法的實例推姻,相當(dāng)于其他語言中的this。
實例方法可以調(diào)用實例屬性际起,也可以調(diào)用類屬性拾碌。類屬性的調(diào)用有兩種格式:self.類屬性 吐葱, 類名.類屬性街望。兩種都是一樣的。但是不要使用self來調(diào)用類屬性弟跑!類屬性是給類使用的灾前,一定要用類名去調(diào)用。
實例方法必須通過實例來調(diào)用
實例屬性:以self.屬性 格式的屬性都為實例屬性孟辑。實例方法是屬于實例的哎甲,每個實例都有單獨(dú)的實例屬性蔫敲。
類屬性:在類內(nèi)部方法的外部定義的屬性,不以self.屬性的格式的屬性炭玫。類屬性是屬于類的奈嘿。所有當(dāng)前類的 實例 都共享 類 的類屬性。
類屬性 相當(dāng)于java中的 static 屬性吞加。
class Foo(object):
class_property = '類屬性'
def __init__(self):
self.instance_property = '實例屬性'
def say(self):
print '實例方法'
print '調(diào)用實例屬性---',self.instance_property
#兩種是一樣的裙犹,但是切記:類屬性要用類名去調(diào)用
#print '調(diào)用類屬性---',self.class_property
print '調(diào)用類屬性---',Foo.class_property
if __name__ == '__main__':
my_foo = Foo()
my_foo.say() #必須通過實例來調(diào)用
類方法:
顧名思義,類方法就是給類使用的方法衔憨。
類方式用 @classmethod裝飾器修飾叶圃。用@classmethod裝飾器修飾的方法都是類方法。
類方法第一個參數(shù)為cls践图,cls表示當(dāng)前類掺冠。
類方法可以調(diào)用類屬性,但是不能調(diào)用實例屬性码党,也不能調(diào)用實例方法德崭。
類方法有兩種調(diào)用方式:
類名.類方法
實例.類方法。
兩種是一樣的闽瓢。但是 切記 類方法是給類使用的 不要使用實例去調(diào)用類方法接癌。一定要用類名去調(diào)用。
類方法相當(dāng)于 Java中的 static方法扣讼。
class Foo(object):
class_property = '類屬性'
def __init__(self):
self.instance_property = '實例屬性'
def say(self):
print '實例方法'
print '調(diào)用實例屬性---',self.instance_property
print '調(diào)用類屬性---',Foo.class_property
@classmethod
def class_say(cls):
print '類方法'
#無法調(diào)用實例屬性缺猛,會報錯
#print '調(diào)用實例屬性',cls.instance_property
#無法調(diào)用實例方法,會報錯
#cls.say()
print '調(diào)用類屬性',cls.class_property
if __name__ == '__main__':
Foo.class_say()
#這樣調(diào)用也可以椭符,但是千萬不要這樣做
# my_foo = Foo()
# my_foo.class_say()
靜態(tài)方法:
靜態(tài)方法是一種普通函數(shù)荔燎,位于類定義內(nèi)部。
靜態(tài)方法以@staticmethod裝飾器修飾销钝。以@staticmethod修飾的方法都是靜態(tài)方法有咨。
靜態(tài)方法無法調(diào)用實例屬性,實例方法蒸健。
靜態(tài)方法內(nèi)部必須使用 類名.類實例座享,類名.類方法 這樣的格式才能調(diào)用類屬性與類方法,否則無法調(diào)用似忧。
靜態(tài)方法與類方法一樣 都是屬于類渣叛。
靜態(tài)方法有兩種調(diào)用方式:
類名.靜態(tài)方法
實例.靜態(tài)方法
兩種是一樣的。但是 切記 靜態(tài)方法是給類使用的 不要使用實例去調(diào)用靜態(tài)方法盯捌。一定要用類名去調(diào)用淳衙。
class Foo(object):
class_property = '類屬性'
def __init__(self):
self.instance_property = '實例屬性'
def say(self):
print '實例方法'
print '調(diào)用實例屬性---',self.instance_property
print '調(diào)用類屬性---',Foo.class_property
@classmethod
def class_say(cls):
print '類方法'
print '調(diào)用類屬性',cls.class_property
@staticmethod
def static_say():
print '靜態(tài)方法'
#必須以類名.類方法或?qū)嵗?才能調(diào)用類方法或者類屬性,否則不能調(diào)用
print '調(diào)用類屬性',Foo.class_property
print '調(diào)用類方法',Foo.class_say()
if __name__ == '__main__':
Foo.static_say()
#這樣調(diào)用也可以,但是千萬不要這樣做
# my_foo = Foo()
# my_foo.static_say()
為什么要存在類方法箫攀?
比如:我們需要進(jìn)行數(shù)據(jù)庫操作肠牲,創(chuàng)建數(shù)據(jù)庫連接只需要進(jìn)行一次即可,不需要每次都創(chuàng)建數(shù)據(jù)庫連接靴跛。
類方法中的類實例只會初始化一次缀雳,以后每次調(diào)用均是同一個類屬性,并不會再次初始化梢睛。只要調(diào)用一次以后俏险,不管在任何模塊中調(diào)用都不會在初始化。
class Foo(object):
class_property = None
@classmethod
def class_say(cls):
print '類方法'
print '類屬性--',cls.class_property
print '類屬性 id ',id(cls.class_property)
if cls.class_property == None:
cls.class_property = time.time()
print '****調(diào)用類屬性',cls.class_property
print '****調(diào)用雷屬性 id ',id(cls.class_property)
@staticmethod
def static_say():
print '靜態(tài)方法'
#必須以類名.類方法或?qū)嵗?才能調(diào)用類方法或者類屬性扬绪,否則不能調(diào)用
print '****調(diào)用類屬性',Foo.class_property
print '****調(diào)用類方法',Foo.class_say()
if __name__ == '__main__':
Foo.class_say()
print '-------'
Foo.class_say()
print '-------'
print '實例'
foo = Foo2()
foo2 = Foo2()
foo.say()
foo2.say()
運(yùn)行結(jié)果如下:
我們可以看到 類屬性只進(jìn)行了一次初始化竖独,以后的調(diào)用均是同一個類實例。
實例屬性則是挤牛,每建立一個實例就會初始化一次莹痢,除非你只要一個實例,在單個模塊中這樣可以墓赴,但是在多個模塊中這是不可能的竞膳。
我們看一個多個模塊中的情況:
#coding=utf-8
#test2.py
import time
class Foo(object):
class_property = None
@classmethod
def class_say(cls):
print '類方法'
print '類屬性--',cls.class_property
print '類屬性 id ',id(cls.class_property)
if cls.class_property == None:
cls.class_property = time.time()
print '****調(diào)用類屬性',cls.class_property
print '****調(diào)用雷屬性 id ',id(cls.class_property)
class Foo2(object):
def __init__(self):
self.instanlce_property = None
def say(self):
print '實例方法'
print '調(diào)用實例屬性 --',self.instanlce_property
print '實例屬性 id',id(self.instanlce_property)
if self.instanlce_property == None:
self.instanlce_property = time.time()
print '****調(diào)用實例屬性 --', self.instanlce_property
print '****實例屬性 id', id(self.instanlce_property)
#coding=utf-8
#test4.py
import test2
def test4_class_foo():
print '類屬性 test4模塊'
foo = test2.Foo
foo.class_say()
def test4_instance_foo():
print '實例 test4模塊'
foo2 = test2.Foo2()
foo2.say()
coding=utf-8
#test3.py
import test2
import test4
def test3_class_foo():
print '類屬性 test3模塊'
foo = test2.Foo
foo.class_say()
def test3_instanlce_foo():
print '實例屬性 test3模塊'
foo2 = test2.Foo2()
foo2.say()
if __name__ == '__main__':
test3_class_foo()
test4.test4_class_foo()
print '實例-----------'
test3_instanlce_foo()
test4.test4_instance_foo()
運(yùn)行結(jié)果如下:
可以清楚的看到 不同模塊之間 類屬性只初始化一次,實例屬性則是诫硕,每建立一個實例就會初始化一次坦辟。除非你只要一個實例,在單個模塊中這樣可以章办,但是在多個模塊中這是不可能的
靜態(tài)方法與類方法的用途是一樣的锉走,沒什么區(qū)別。
但是為什么要存在靜態(tài)方法呢藕届?
為了更加面向?qū)ο笤O(shè)計(oop)
首先挪蹭,靜態(tài)方法就是一普通函數(shù)
其次,靜態(tài)方法是與類無關(guān)的休偶。也就是說 靜態(tài)方法實現(xiàn)的功能可以是與所存在的類所實現(xiàn)的功能沒有任何關(guān)系梁厉。類方法的功能,則是與類所實現(xiàn)的功能相關(guān)聯(lián)的踏兜。打個比方就是 :類方法相當(dāng)于類的親兒子词顾,靜態(tài)方法就相當(dāng)于收養(yǎng)的流浪貓。
oop的思想是 一切以類為基礎(chǔ)碱妆。
為了更加oop肉盹,所有說就把普通函數(shù)塞進(jìn)來類里面,這就是靜態(tài)方山橄。