類
類(Class)是對某種類型的對象定義變量和方法的原型。它表示對現(xiàn)實(shí)生活中一類具有共同特征的事物的抽象,是面向?qū)ο缶幊痰幕A(chǔ)。
python中,私有的屬性或方法都必須前面加__(雙下劃線)
首先讓我們看一下Python中類的定義:
class People:
galaxy = 'Galactic' #類屬性(公有屬性)
__star = 'Earth' #類屬性(私有屬性)
def __init__(self, name, age):
self.__name = name #(實(shí)例屬性:私有屬性)
self.age = age #(實(shí)例屬性:公有屬性)
#類方法
@classmethod
def say(cls, mess):
print "I say %s" % mess
#實(shí)例方法
def code(self, language):
print "I can code use %s" % language
#靜態(tài)方法
@staticmethod
def run(velocity):
print "I run %f km/h" % velocity
Python中的init(self, ...)在生成對象時調(diào)用(稱內(nèi)置方法),self參數(shù)相當(dāng)于Java中的this(可以寫成其他的參數(shù)名,不過一般都寫成self,便于理解),不需要顯示調(diào)用(即可以不用寫),系統(tǒng)默認(rèn)執(zhí)行,且支持重載,跟Java中的構(gòu)造函數(shù)類似,其它內(nèi)置方法還有del(self), __cmp__(), __len__()等等
以上類中出現(xiàn)的概念,下面都會詳細(xì)的介紹到
python中區(qū)分類屬性和實(shí)例屬性
類屬性
類屬性就是類本身(類也是一個對象,所有也可以叫類對象)所擁有的屬性,可以被該類的所有實(shí)例化對象所共有,在內(nèi)存中只有一個副本,和Java中的靜態(tài)成員變量相似。對于公有的類屬性,在類外面,既可以通過==類對象本身.屬性==訪問,也可以通過==實(shí)例對象.屬性==進(jìn)行訪問。
class People:
name = 'nanxue'
p = People() #實(shí)例化時,并不需要new
print p.name # nanxue
print People.name # nanxue
注意:雖然類定義的時候,類名后緊跟了冒號(class People:),但實(shí)例化時,必須寫成 instance = className() 的形式,如果類中有構(gòu)造函數(shù)的重載,則必須寫成重載的形式,比如這樣
class People:
name = 'nanxue'
def __init__(self,age):
self.age = age
p = People(20) #實(shí)例化時,并不需要new
p = People() #error (TypeError: __init__() takes exactly 2 arguments (1 given))
實(shí)際上Python2.2以后,規(guī)定所有類都繼承自object基類,所以其實(shí)也可以這么寫 class People(object):
而私有的類屬性不管是類對象還是實(shí)例對象,在類外面都不能訪問,例如下面的訪問形式就會出錯
class People:
__name = 'nanxue'
p = People()
print p.__name # error(AttributeError: class People has no attribute '__name')
print People.__name # error(AttributeError: People instance has no attribute '__name')
實(shí)例屬性
而實(shí)例屬性,只能通過實(shí)例對象訪問(類對象訪問不到,見第一種),實(shí)例屬性既可以在初始化的過程定義(init函數(shù)中通過self.屬性),也可以在實(shí)例化后動態(tài)的添加(此時,該屬性為這個實(shí)例所特有)
- 第一種
class People:
name = 'nanxue'
def __init__(self,age):
self.age = age
p = People(12)
print p.name # nanxue
print p.age # 12
print People.age #error(AttributeError: class People has no attribute 'age')
- 第二種
class People:
name = 'nanxue'
p = People()
p.age = 12
print p.name # nanxue
print p.age # 12
pp = People()
print pp.age #error(AttributeError: People instance has no attribute 'age')
與類屬性相同,在初始化函數(shù)中定義的私有實(shí)例屬性在類外面是訪問不到的,但是通過動態(tài)添加的私有屬性可以訪問的到
class People:
name = 'nanxue'
def __init__(self,age):
self.__age = age
p = People(20)
print p.name # nanxue
print p.__age # error(AttributeError: People instance has no attribute '__age')
p.__sex = 2
print p.__sex # 2
此時,還存在一種情況,就是在類中定義了一個類屬性,實(shí)例化后也動態(tài)添加一個同名屬性,會怎么樣呢?,會覆蓋嗎?
class People:
name = 'nanxue'
def __init__(self,age):
self.age = age
p = People(20)
print p.name # nanxue
print p.age # 20
#同名屬性
p.age = 50
print p.age # 50
p.name = 'aaa'
print p.name # aaa
print People.name # nanxue
del p.name
print p.name # nanxue
可以看到,實(shí)例對象會產(chǎn)生一個同名的實(shí)例屬性,強(qiáng)制屏蔽掉類屬性,類屬性還是原來的值,如果刪除掉實(shí)例屬性,則恢復(fù)為類屬性,因此要修改類屬性的值,需通過類對象修改
class People:
name = 'nanxue'
p = People()
print p.name # nanxue
#同名屬性
p.name = 'aaa'
print p.name # aaa
#新的實(shí)例對象
pp = People()
print pp.name # nanxue
#修改類屬性
People.name = 'bbb'
print p.name # aaa
print pp.name # bbb
方法的區(qū)別
實(shí)例方法
顧名思義,為該類的實(shí)例所有,不能通過類對象引用實(shí)例方法,至少有一個參數(shù)且必須為實(shí)例對象,也必須作為該方法的第一個參數(shù)
class People:
name = 'nanxue'
#實(shí)例方法
def code(self):
return self.name
p = People()
print p.code() # nanxue
print Peopel.code() # error(unbound method code() must be called with People instance as first argument (got nothing instead))
當(dāng)同時存在同名的類屬性與實(shí)例屬性時,實(shí)例屬性優(yōu)先級更高
類方法
方法前需加修飾符@classmethod,實(shí)例對象與類對象都可以引用,第一個參數(shù)必須是類對象,一般寫作cls
class People:
name = 'nanxue'
#類方法
@classmethod
def eat(cls):
return cls.name
p = People()
print p.eat() # nanxue
print People.eat() # nanxue
類方法可對類屬性進(jìn)行修改
class People:
name = 'nanxue'
#類方法
@classmethod
def setName(cls, name):
cls.name = name
@classmethod
def getName(cls):
return cls.name
p = People()
print p.getName() # nanxue
print People.getName() # nanxue
p.setName('xiaonan')
#People.setName('xiaonan')
print p.getName() #xiaonan
print People.getName() #xiaonan
靜態(tài)方法
靜態(tài)方法前需要加修飾符@staticmethod,不需要額外定義參數(shù)
class People:
name = 'nanxue'
#靜態(tài)方法
@staticmethod
def getStaticName():
return People.name
p = People()
print p.getSaticName() # error(People instance has no attribute 'getSaticName')
print People.getSaticName() # nanxue