【Python】 如何動態新增類屬性與方法
一些概念
涉及到一些基礎概念,本章要討論的相關術語。但是有些概念又是一時半會講不清楚,所以筆者儘量找到簡練形象的描述,並附上參考連結。
- 物件
- 屬性
- 方法
- 類
- 例項
物件(object):在面向物件程式設計中(OPP),萬物都是物件。物件應該具有屬性(就是上面的狀態,因為屬性更常用)、方法(就是上面的行為,方法跟常被使用)和標識。
既然萬物都是物件,那麼,某個具體的人也是物件,這是當然的事情。假設這個具體的人就是德藝雙馨的蒼老師,她是一個物件。這個蒼老師具有哪些特徵呢?我錯了,寫到這裡發現不能用蒼老師為物件的例子,因為容易讓讀者不專心學習了。我換一個吧,以某個王美女為物件說明(這個王美女完全是虛構的,請不要對號入座,更不要想入非非,如果雷同,純屬巧合)
屬性:即狀態(state),包括這個物件已有的屬性(通常是類裡面已經定義好的)在加上物件具有的當前屬性值(這些屬性往往是動態的)
王美女這個物件具有某些特徵,眼睛,大;腿,長;面板,白。當然,既然是美女,肯定還有別的顯明特徵,讀者可以自己假設去。如果用“物件”的術語來說明,就說這些特徵都是她的屬性。也就是說屬性是一個物件做具有的特徵,或曰:是什麼。。
方法:即行為(behavior),是指一個物件如何影響外界及被外界影響,表現為物件自身狀態的改變和資訊的傳遞。
王美女除了具有上面的特徵之外,她還能做一些事情,比如她能唱歌、會吹拉彈唱等。這些都是她能夠做的事情。用“物件”的術語來說,就是她的“方法”。即方法就是物件能夠做什麼
。
類:在面向物件程式設計,類(class)是一種面向物件計算機程式語言的構造,是建立物件的藍圖,描述了所建立的物件共同的屬性和方法。
首先要明確,類是對某一群具有同樣屬性和方法的物件的抽象。比如這個世界上有很多長翅膀並且會飛的生物,於是聰明的人們就將它們統一稱為“鳥”——這就是一個類,雖然它也可以稱作“鳥類”。
例項:類僅僅是對物體的抽象描述,並不是某個具體物件.。由類變成一個例項的過程叫做類的例項化。
在程式設計界,有這樣一句話,說“類是例項工廠”,什麼意思呢?工廠是幹什麼的?生產物品,比如生產電腦。一個工廠可以生產好多電腦。那麼,類,就能“生產”好多例項,所以,它是“工廠”。
定義時新增
通常在定義類的時候,新增屬性和方法。
class Person(object): #建立類
def __init__(self, name): #建構函式
self.name = name
def getName(self): #類中的方法(函式)
return self.name
def color(self, color):
print "%s is %s" % (self.name, color)
girl = Person('canglaoshi') #例項化
name = girl.getName() #呼叫方法(函式)
print "the person's name is: ", name
girl.color("white") #呼叫方法(函式)
print "------"
print girl.name #例項的屬性
__init__()是建構函式,在類例項化之後,就立即執行了這個建構函式。作為首次初始化使用。
self 類裡面的函式,第一個引數是self。在類內部,就是將所有傳入的資料都賦給一個變數,通常這個變數的名字是self。也就是說,self接收例項化的所有資料,self就是一個例項。
在函式外部,類的例項化物件 girl 和函式內部的slef是一回事。girl.name 相當於 slef.name
儲存並執行
$ python 20701.py
the person's name is: canglaoshi
canglaoshi is white
------
canglaoshi
動態新增
有些情況沒有在定義類是新增它的屬性或者方法(比如,我們使用第三方函式庫的時候)。但可以通過動態的方法,在程式執行的過程中新增。
動態新增屬性
第一種:使用物件名.屬性名新增,示例如下:
p.age = 18
第二種:使用setattr函式新增,示例如下:
if not hasattr(p,'age'):
setattr(p,'age',18)
hasattr
是用來判斷一個物件是否有某個屬性,而setattr是用來給某個物件新增屬性,並且指定這個屬性的值。
動態新增方法
動態新增例項方法:
使用types.MethodType這個方法了,示例程式碼如下:
import types
class Person(object):
def __init__(self,name):
self.name = name
def run(self):
print('%s在奔跑' % self.name)
p1 = Person('p1')
p1.run = types.MethodType(run,p1)
p1.run()
其中types.MethodType的第一個引數是這個函式本身,第二個引數是在呼叫run這個函式的時候,傳給run方法的第一個引數。
動態新增類方法:
新增類方法,是把這個方法新增給類。因此新增類方法的時候不是給物件新增,而是給類新增。
直接將這個函式賦值給類就可以了,但是需要使用classmethod裝飾器將這個方法設定為一個類方法。示例程式碼如下:
import types
class Person(object):
country = 'china'
def __init__(self,name):
self.name = name
@classmethod
def run(cls):
print('%s在奔跑' % cls.country)
Person.run = run
Person.run()
動態新增靜態方法:
新增靜態方法,是把這個方法新增給類。因此也是直接給類新增的,並且使用staticmethod這個裝飾器。示例方法如下:
import types
class Person(object):
country = 'china'
def __init__(self,name):
self.name = name
@staticmethod
def run():
print('在奔跑')
Person.run = run
Person.run()
動態刪除屬性和方法:
del 物件.屬性名
delattr(物件,"屬性名")
__slots__限制動態新增屬性或方法
示例程式碼如下:
class Person(object):
__slots__ = ('name','age')
def __init__(self,name):
self.name = name
p = Person('zhiliao')
setattr(p,'height',180)