Python如何實(shí)現(xiàn)property、classmethod和staticmethod

img.jpg

Python中面向?qū)ο缶幊躺婕暗模?strong>property、classmethodstaticmethod,通常會被認(rèn)為它們是Python中的關(guān)鍵字,其實(shí)不然,它們都是通過裝飾器(decorator)和描述器(descriptor)特性實(shí)現(xiàn)的特殊類,Python中的裝飾器(decorator)與描述器(descriptor)。

@property的實(shí)現(xiàn)

property為例,以下通過roperty實(shí)現(xiàn)property的功能,通過property可以方便地為一個(gè)屬性定義set和get方法

class roperty(object):

    # 裝飾器類的語法和裝飾器方法類似,
    # @roperty等價(jià)于roperty(...)
    # 入?yún)Ⅲw現(xiàn)在初始化方法中
    def __init__(self, func):
        self.__name__ = func.__name__
        self.getF = func
        self.setF = None
        pass

    def setter(self, func):
        self.setF = func
        return self

    def __set__(self, instance, value):
        self.setF(instance, value)
        pass

    def __get__(self, instance, owner):
        return self.getF(instance)

class A(object):
    
    # 利用roperty像property一樣定義屬性
    # 這里等價(jià)于name = roperty(name)
    # 利用裝飾器語法,name被賦值為roperty的實(shí)例
    @roperty
    def name(self):
        print('get name1')
        return self.__name
        
    # 由于name被賦值為roperty的實(shí)例
    # 為了演示上的區(qū)分,方法名為name1,實(shí)際開發(fā)中用name即可
    # 以下等價(jià)于name1 = name.setter(name1)
    @name.setter
    def name1(self, n):
        print('set name')
        self.__name = n

a = A()

# 值得注意的是,經(jīng)過裝飾器語法后A.name已經(jīng)是roperty對象(這里roperty對象既是一個(gè)裝飾器又是一個(gè)描述器)
# 根據(jù)描述器的特性,a.name賦值會觸發(fā)描述器的__set__方法,繼而調(diào)用name屬性定義的set方法
a.name = 'name1111'

# 根據(jù)描述器的特性,a.name讀取會觸發(fā)描述器的__get__方法,繼而調(diào)用name屬性定義的get方法
print(a.name)

property屬于數(shù)據(jù)型描述器(data descriptor),同時(shí)也是一個(gè)以class定義裝飾器。

class中函數(shù)的調(diào)用

通常來講,class中支持定義實(shí)例方法、@classmethod修飾的類方法和@staticmethod修飾的靜態(tài)方法,這幾種方法的區(qū)別:

  • 普通方法:
    不需要修飾符,實(shí)例調(diào)用時(shí)自動傳入第一個(gè)參數(shù)為實(shí)例,類調(diào)用時(shí)不自動傳入第一個(gè)參數(shù)
  • 類方法:
    通過類或者實(shí)例調(diào)用時(shí),自動傳入第一個(gè)參數(shù)為類
  • 靜態(tài)方法:
    通過類或者實(shí)例調(diào)用時(shí),不自動傳入第一個(gè)參數(shù)

普通方法的調(diào)用行為是Python的默認(rèn)行為,類方法和靜態(tài)方法的調(diào)用行為則是通過classmethodstaticmethod實(shí)現(xiàn)的。

@classmethod和@staticmethod的實(shí)現(xiàn)

以下通過classmethod1staticmethod1實(shí)現(xiàn)classmethodstaticmethod的功能

class classmethod1(object):

    def __init__(self, func):
        self.sf = func

    def __get__(self, instance, owner):
        return lambda *args, **kwargs: self.sf(owner, *args, **kwargs)

class staticmethod1(object):

    def __init__(self, func):
        self.sf = func

    def __get__(self, instance, owner):
        return lambda *args, **kwargs: self.sf(*args, **kwargs)

class A(object):

    def name(self):
        print('instance.name')

    @classmethod1
    def className(cls):
        print('{}.name'.format(cls))

    @staticmethod1
    def staticName(ipt):
        print('{}.name'.format(ipt))

a = A()
a.name()
A.className()
a.className()
A.staticName('static')
a.staticName('static')

>>> instance.name
>>> A.name
>>> A.name
>>> static.name
>>> static.name
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容