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