1. 程式人生 > 其它 >python動態新增屬性和方法

python動態新增屬性和方法

一、動態語言相關概念

1.1動態語言

  • 在執行時程式碼可以根據某些條件改變自身結構
  • 可以在執行時引進新的函式、物件、甚至程式碼,可以刪除已有的函式等其他結構上的變化
  • 常見的動態語言:Object-C、C#、JavaScript、PHP、Python、Erlang

1.2 動態型別語言

  • 在執行期間檢查資料型別的語言
  • 資料型別不是在編譯階段決定的,而是把型別繫結延後到了執行階段
  • 常見的動態型別語言:Python、Ruby、Erlang、JavaScript、swift、PHP、Perl

1.3強型別語言

  • 一旦一個變數被指定了某個資料型別,如果不經過強制型別轉換,那麼它就永遠是這個資料型別
  • 常見的強型別語言:Java、C#、Python、Object-C、Ruby

Python是動態語言,動態型別語言,也是強型別語言。所以Python可以在執行時改變自身結構,動態新增/刪除屬性和方法。接下來將介紹Python如何動態新增屬性和方法。

二、動態新增屬性

2.1 新增物件屬性

class Person(object):
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

zhangsan = Person("張三", 18)
zhangsan.addr = "北京"    # 類物件zhangsan動態新增物件屬性addr
print(zhangsan.name)    # 張三
print(zhangsan.age)     # 
18 print(zhangsan.addr) # 北京 lisi = Person("李四", 28) print(lisi.name) # 李四 print(lisi.age) # 28 print(lisi.addr) # 'Person' object has no attribute 'addr'

由以上程式碼可知,Person類有兩個屬性:name和age。通過[物件名.屬性名]給類物件zhangsan動態添加了物件屬性addr,而Person的另一個類物件lisi卻不能呼叫這個屬性。

注:通過物件名新增的物件屬性,只有這個物件能使用

2.2 新增類屬性

class Person(object):
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

Person.addr = "北京"  # 類Person動態新增類屬性addr

zhangsan = Person("張三", 18)
print(zhangsan.name)    # 張三
print(zhangsan.age)     # 18
print(zhangsan.addr)    # 北京

lisi = Person("李四", 28)
print(lisi.name)    # 李四
print(lisi.age)     # 28
print(lisi.addr)    # 北京

由以上程式碼可知,通過[類名.屬性名]給類Person動態添加了類屬性addr,Person的類物件zhangsan和lisi都能呼叫這個屬性

注:通過類名新增的類屬性,這個類的所有物件都能使用

三、動態新增方法

類中有三種方法,例項方法,靜態方法和類方法,三種方法的區別如下:

  • 例項方法:需要繫結要一個物件上,第一個引數預設使用self,會把物件作為第一個引數傳遞進來
  • 靜態方法:使用裝飾器@staticmethod進行定義,類和物件都可以呼叫,不需要預設引數
  • 類方法:使用裝飾器@classmethod進行定義,類和物件都可以呼叫,第一個引數預設使用cls,會把類作為第一個引數傳遞進來

3.1 新增例項方法

import types

class Person(object):
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

    def eat(self):
        print("---正在吃---")

def run(self):
    print("---正在跑---")

zhangsan = Person("張三", 18)
zhangsan.eat()  # ---正在吃---
zhangsan.run = types.MethodType(run, zhangsan)  # 類物件zhangsan動態新增物件方法run()
zhangsan.run()  # ---正在跑---

lisi = Person("李四", 28)
lisi.eat()  # ---正在吃---
lisi.run()  # 'Person' object has no attribute 'run'

由以上程式碼可知,Person類有一個方法:eat()方法。通過[types.MethodType(方法名, 物件名)]給類物件zhangsan動態添加了物件方法run(),同理,Person的另一個類物件lisi不能呼叫這個方法

注:通過物件名新增的物件方法,只有這個物件能使用

3.2 新增靜態方法

class Person(object):
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

    def eat(self):
        print("---正在吃---")

@staticmethod
def staticRun():
    print("---正在跑---")

Person.staticRun = staticRun    # 類Person動態新增靜態方法staticRun()

Person.staticRun()  # ---正在跑---

zhangsan = Person("張三", 18)
zhangsan.eat()        # ---正在吃---
zhangsan.staticRun()  # ---正在跑---

lisi = Person("李四", 28)
lisi.eat()        # ---正在吃---
lisi.staticRun()  # ---正在跑---

由以上程式碼可知,通過[類名.靜態方法名]給類Person動態添加了靜態方法staticRun(),Person類的Person的類物件zhangsan和lisi都能呼叫這個方法

注:通過類名新增的靜態方法,這個類及這個類的所有物件都能使用

3.3 新增類方法

class Person(object):
    def __init__(self, newName, newAge):
        self.name = newName
        self.age = newAge

    def eat(self):
        print("---正在吃---")

@classmethod
def classRun(cls):
    print("---正在跑---")

Person.classRun = classRun    # 類Person動態新增類方法classRun()

Person.classRun()  # ---正在跑---

zhangsan = Person("張三", 18)
zhangsan.eat()        # ---正在吃---
zhangsan.classRun()  # ---正在跑---

lisi = Person("李四", 28)
lisi.eat()        # ---正在吃---
lisi.classRun()  # ---正在跑---

由以上程式碼可知,通過[類名.類方法名]給類Person動態添加了類方法classRun(),Person類的Person的類物件zhangsan和lisi都能呼叫這個方法

注:通過類名新增的類方法,這個類及這個類的所有物件都能使用