python高階-動態特性(20)
一、動態語⾔的定義
動態語言是在執行時確定資料型別的語言。變數使用之前不需要型別宣告,通常變數的型別是被賦值的那個值的型別。現在比較熱門的動態語言有:Python、PHP、JavaScript、Objective-C等,而 C 、 C++ 等語言則不屬於動態語言。
二、執行的過程中給物件繫結(新增)屬性
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age p = Person("小明","24") print(p.name) print(p.age)
執行結果為:
小明 24
這裡我們只定義了name和age兩個屬性,但是在類已經定義好了之後,我們仍然可以往裡面新增屬性,這就是動態語言的好處,動態的給例項繫結屬性:
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age p = Person("小明","24") print(p.name) print(p.age) #動態新增屬性 p.sex = "男" print(p.sex)
執行結果為:
小明 24 男
三、執行的過程中給類繫結(新增)屬性
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age P1 = Person("小明",24) print(P1.sex)
執行結果為:
Traceback (most recent call last): File "C:\Users\Se7eN_HOU\Desktop\test.py", line 8, in <module> print(P1.sex) AttributeError: 'Person' object has no attribute 'sex'
這是程式報錯說,Person沒有sex這個屬性,我們可以通過給Person動態繫結屬性,解決問題
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age P1 = Person("小明",24) #動態給類新增屬性 Person.sex = "男" print(P1.sex)
這個時候在執行就不會出錯,而且會打印出P1.sex為男
四、執行的過程中給類繫結(新增)方法
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age def eat(self): print("正在吃東西") P1 = Person("小明",24) P1.eat() P1.run()
執行結果為:
正在吃東西 Traceback (most recent call last): File "C:\Users\Se7eN_HOU\Desktop\test.py", line 11, in <module> P1.run() AttributeError: 'Person' object has no attribute 'run'
說明:正在吃東西打印出來了,說明eat函式被執行,但是後面報錯說沒有run這個屬性,但是我想在類建立好了以後,在執行的時候動態的新增run方法怎麼辦呢?
#動態新增方法需要匯入types模組 import types class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age def eat(self): print("正在吃東西") #定義好需要動態新增的方法 def run(self): print("在跑步") P1 = Person("小明",24) #正常呼叫類裡面的函式 P1.eat() #給物件動態繫結方法 P1.run = types.MethodType(run,P1) #物件呼叫動態繫結的方法 P1.run()
執行結果為:
正在吃東西 在跑步
打印出來“在跑步”說明run方法被正常執行了
動態繫結類方法和靜態方法
#動態新增方法需要匯入types模組 import types class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age def eat(self): print("正在吃東西") #定義好需要動態新增的例項方法 def run(self): print("在跑步") #定義好需要動態新增的類方法 @classmethod def dynamicClassMethod(cls): print("這是一個動態新增的類方法") #定義好需要動態新增的靜態方法 @staticmethod def dynamicStaticMethod(): print("這是一個動態新增的靜態方法") P1 = Person("小明",24) #正常呼叫類裡面的函式 P1.eat() #給物件動態繫結方法 #MethodType(引數1,引數2) #引數1:是動態繫結哪個方法,只寫方法名即可 #引數2:是把這個方法動態的繫結給誰 P1.run = types.MethodType(run,P1) P1.run() #動態繫結類方法的使用 Person.dynamicClassMethod = dynamicClassMethod Person.dynamicClassMethod() #動態繫結靜態方法的使用 Person.dynamicStaticMethod = dynamicStaticMethod Person.dynamicStaticMethod()
總結:
- 給物件繫結屬性直接在使用前進行賦值使用即可
- 給物件動態繫結方法需要import types模組
- 給物件動態繫結例項方法,需要使用type.MethodType()方法
- 給類新增類方法和靜態方法,也是直接在使用前賦值即可使用
五、執行的過程中刪除屬性、方法
刪除的方法:
- del 物件.屬性名
- delattr(物件, "屬性名")
class Person(object): def __init__(self,name=None,age=None): self.name=name self.age=age P1 = Person("小明",24) print("---------刪除前---------") print(P1.name) del P1.name print("---------刪除後---------") print(P1.name)
執行結果為:
---------刪除前--------- 小明 ---------刪除後--------- print(P1.name)AttributeError: 'Person' object has no attribute 'name'
六、__slots__
動態語言:可以在執行的過程中,修改程式碼
靜態語言:編譯時已經確定好程式碼,執行過程中不能修改
如果我們想要限制例項的屬性怎麼辦?比如,只允許對Person例項新增name和age屬性。
為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變數,來限制該class例項能新增的屬性:
class Person(object): __slots__=("name","age") p = Person() p.name = "老王" p.age = 40 print(p.name) print(p.age) #slots之外的屬性 p.sex = "男" print(p.sex)
執行結果為:
老王 40 p.sex = "男" AttributeError: 'Person' object has no attribute 'sex'
注意:
- 使用__slots__要注意,__slots__定義的屬性僅對當前類例項起作用,對繼承的子類是不起作用的