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 Obj(object):
    def __init__(self):
        self.name = '張亞飛'


obj = Obj()
obj.age = 23
print(obj.age)
obj2 = Obj()
print(obj2.age)

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

2.2 新增類屬性

Obj.score = 100
print(obj.score)
print(obj2.score)
  由以上程式碼可知,通過[類名.屬性名]給類Person動態添加了類屬性addr,Person的類物件obj和obj2都能呼叫這個屬性     注:通過類名新增的類屬性,這個類的所有物件都能使用
  三、動態新增方法

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

from types import MethodType


class Obj(object):
    # __slots__ = ('name', 'age')

    def __init__(self):
        self.name = '張亞飛'


def set_score(self, score):
    self.score = score


@staticmethod
def static_func():
    print('static_func')


@classmethod
def class_func(cls):
    print('class_method')
“““
類中有三種方法,例項方法,靜態方法和類方法,三種方法的區別如下:
例項方法:需要繫結要一個物件上,第一個引數預設使用self,會把物件作為第一個引數傳遞進來
靜態方法:使用裝飾器@staticmethod進行定義,類和物件都可以呼叫,不需要預設引數
類方法:使用裝飾器@classmethod進行定義,類和物件都可以呼叫,第一個引數預設使用cls,會把類作為第一個引數傳遞進來
”””
# 動態新增例項方法
obj.set_score = MethodType(set_score, obj)
obj.set_score(99)
print(obj.score)
"""
由以上程式碼可知,Person類有一個方法:eat()方法。通過[types.MethodType(方法名, 物件名)]給類物件zhangsan動態添加了物件方法run(),同理,Person的另一個類物件lisi不能呼叫這個方法
注:通過物件名新增的物件方法,只有這個物件能使用
"""
# 新增靜態方法
Obj.static_func = static_func
Obj.static_func()
obj.static_func()
"""
由以上程式碼可知,通過[類名.靜態方法名]給類Person動態添加了靜態方法staticRun(),Person類的Person的類物件zhangsan和lisi都能呼叫這個方法
注:通過類名新增的靜態方法,這個類及這個類的所有物件都能使用
"""
# 新增類方法
Obj.class_func = class_func
Obj.class_func()
obj.class_func()
"""
由以上程式碼可知,通過[類名.類方法名]給類Person動態添加了類方法classRun(),Person類的Person的類物件zhangsan和lisi都能呼叫這個方法
注:通過類名新增的類方法,這個類及這個類的所有物件都能使用
"""

四、__slots__的使用

  通過以上內容,我們知道了如何動態的新增屬性和方法。但是,如果我們想要限制class的屬性該怎麼辦?例如:只允許Person例項新增name和age屬性。為了達到這個目的,Python允許在定義class的時候,定義一個特殊變數__slots__來限制該class能新增的屬性。

class Obj(object):
    __slots__ = ('name', 'age')


obj.name = 'zhangyafei'
obj.age = 23
obj.score = 99  # AttributeError: 'Obj' object has no attribute 'score'

obj = Obj()
print(obj.score)
obj.score = 99  # AttributeError: 'Obj' object attribute 'score' is read-only

通過以上程式碼可知,__slots__對Person類的動態新增沒有限制,而Person類物件zhangsan不能再動態新增物件屬性和方法。

對於__slot__有以下幾個需要注意的地方:

  • __slots__只對類物件進行限制,不對類進行限制
  • __slots__不僅限制類物件的屬性,還限制類物件的方法
  • __slots__僅對當前類起作用,對繼承的子類不起作用
  • 在子類中定義__slots__,子類允許定義的屬性就是自身的__slots__加上父類的__slots__