1. 程式人生 > >【Python】 如何動態新增類屬性與方法

【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)