最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解python單例模式與metaclass

 更新時(shí)間:2016年01月15日 10:14:56   作者:quietin  
這篇文章主要介紹了python單例模式與metaclass,文章介紹了單例模式的實(shí)現(xiàn)方式

單例模式的實(shí)現(xiàn)方式

將類實(shí)例綁定到類變量上

class Singleton(object):
  _instance = None

  def __new__(cls, *args):
    if not isinstance(cls._instance, cls):
      cls._instance = super(Singleton, cls).__new__(cls, *args)
    return cls._instance

但是子類在繼承后可以重寫__new__以失去單例特性

class D(Singleton):

  def __new__(cls, *args):
    return super(D, cls).__new__(cls, *args)

使用裝飾器實(shí)現(xiàn)

def singleton(_cls):
  inst = {}

  def getinstance(*args, **kwargs):
    if _cls not in inst:
      inst[_cls] = _cls(*args, **kwargs)
    return inst[_cls]
  return getinstance

@singleton
class MyClass(object):
  pass

問題是這樣裝飾以后返回的不是類而是函數(shù),當(dāng)然你可以singleton里定義一個(gè)類來解決問題,但這樣就顯得很麻煩了

使用__metaclass__,這個(gè)方式最推薦

class Singleton(type):
  _inst = {}
  
  def __call__(cls, *args, **kwargs):
    if cls not in cls._inst:
      cls._inst[cls] = super(Singleton, cls).__call__(*args)
    return cls._inst[cls]


class MyClass(object):
  __metaclass__ = Singleton

metaclass

元類就是用來創(chuàng)建類的東西,可以簡單把元類稱為“類工廠”,類是元類的實(shí)例。type就是Python的內(nèi)建元類,type也是自己的元類,任何一個(gè)類

>>> type(MyClass)
type
>>> type(type)
type

python在創(chuàng)建類MyClass的過程中,會(huì)在類的定義中尋找__metaclass__,如果存在則用其創(chuàng)建類MyClass,否則使用內(nèi)建的type來創(chuàng)建類。對(duì)于類有繼承的情況,如果當(dāng)前類沒有找到,會(huì)繼續(xù)在父類中尋找__metaclass__,直到所有父類中都沒有找到才使用type創(chuàng)建類。
如果模塊里有__metaclass__的全局變量的話,其中的類都將以其為元類,親自試了,沒這個(gè)作用,無任何影響

查看type的定義,

type(object) -> the object's type
type(name, bases, dict) -> a new type

所以利用type定義一個(gè)類的元類,可以用函數(shù)返回一個(gè)上面第二種定義的對(duì)象,也可以繼承type并重寫其中的方法。

直接使用type生成的對(duì)象作為元類,函數(shù)作用是使屬性變?yōu)榇髮?/p>

def update_(name, bases, dct):
  attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
  uppercase_attr = {name.upper(): value for name, value in attrs}
  return type(name, bases, uppercase_attr)


class Singleton(object):
  __metaclass__ = update_
  abc = 2

d = Singleton()
print d.ABC
# 2

上一節(jié)中,單例模式元類實(shí)現(xiàn)用的是類繼承方式,而對(duì)于第一種__new__的方式,本質(zhì)上調(diào)用的是type.__new__,不過使用super能使繼承更清晰一些并避免一些問題

這里簡單說明一下,__new__是在__init__前調(diào)用的方法,會(huì)創(chuàng)建對(duì)象并返回,而__init__則是用傳入的參數(shù)將對(duì)象初始化??匆幌聇ype中這兩者以及__call__的實(shí)現(xiàn)

def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
    """
    type(object) -> the object's type
    type(name, bases, dict) -> a new type
    # (copied from class doc)
    """
    pass

@staticmethod # known case of __new__
def __new__(S, *more): # real signature unknown; restored from __doc__
  """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
  pass

def __call__(self, *more): # real signature unknown; restored from __doc__
  """ x.__call__(...) <==> x(...) """
  pass

前面提到類相當(dāng)于元類的實(shí)例化,再聯(lián)系創(chuàng)建單例模式時(shí)使用的函數(shù),用的是__call__,其實(shí)用三種magic method中任何一種都是可以的,來看一下使用元類時(shí)各方法的調(diào)用情況

class Basic(type):
  def __new__(cls, name, bases, newattrs):
    print "new: %r %r %r %r" % (cls, name, bases, newattrs)
    return super(Basic, cls).__new__(cls, name, bases, newattrs)

  def __call__(self, *args):
    print "call: %r %r" % (self, args)
    return super(Basic, self).__call__(*args)

  def __init__(cls, name, bases, newattrs):
    print "init: %r %r %r %r" % (cls, name, bases, newattrs)
    super(Basic, cls).__init__(name, bases, dict)


class Foo:
  __metaclass__ = Basic

  def __init__(self, *args, **kw):
    print "init: %r %r %r" % (self, args, kw)

a = Foo('a')
b = Foo('b')

結(jié)果

new: <class '__main__.Basic'> 'Foo' () {'__module__': '__main__', '__metaclass__': <class '__main__.Basic'>, '__init__': <function init at 0x106fd5320>}
init: <class '__main__.Foo'> 'Foo' () {'__module__': '__main__', '__metaclass__': <class '__main__.Basic'>, '__init__': <function init at 0x106fd5320>}
call: <class '__main__.Foo'> ('a',)
init: <__main__.Foo object at 0x106fee990> ('a',) {}
call: <class '__main__.Foo'> ('b',)
init: <__main__.Foo object at 0x106feea50> ('b',) {}

元類的__init__和__new__只在創(chuàng)建類Foo調(diào)用了一次,而創(chuàng)建Foo的實(shí)例時(shí),每次都會(huì)調(diào)用元類的__call__方法

以上就是本文的全部內(nèi)容,對(duì)python單例模式與metaclass進(jìn)行了描述,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Python使用get_text()方法從大段html中提取文本的實(shí)例

    Python使用get_text()方法從大段html中提取文本的實(shí)例

    今天小編就為大家分享一篇Python使用get_text()方法從大段html中提取文本的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • python中列表添加的四種方法小結(jié)

    python中列表添加的四種方法小結(jié)

    這篇文章主要介紹了python中列表添加的四種方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Python中的xmltodict模塊詳解

    Python中的xmltodict模塊詳解

    這篇文章主要介紹了Python中的xmltodict模塊詳解,xmltodict一般我們用 json、yaml 轉(zhuǎn)換成 dict 可能多一些,xml 轉(zhuǎn)到 dict 可能用得不多,不過,還是可以來看一看,需要的朋友可以參考下
    2023-07-07
  • Python實(shí)現(xiàn)一鍵PDF轉(zhuǎn)Word(附完整代碼及詳細(xì)步驟)

    Python實(shí)現(xiàn)一鍵PDF轉(zhuǎn)Word(附完整代碼及詳細(xì)步驟)

    pdf2docx 是一個(gè)基于 Python 的第三方庫,專門用于將 PDF 文件轉(zhuǎn)換為可編輯的 Word 文檔,下面我們就來看看如何通過pdf2docx實(shí)現(xiàn)一鍵將PDF轉(zhuǎn)為Word吧
    2025-05-05
  • Python使用matplotlib顯示圖像實(shí)例

    Python使用matplotlib顯示圖像實(shí)例

    在Python項(xiàng)目中處理圖像數(shù)據(jù)之前,需要確保安裝了matplotlib庫,它是一個(gè)用于繪制圖表和圖像顯示的工具,若尚未安裝,可以使用pip命令進(jìn)行安裝,安裝完成后,可以通過matplotlib的pyplot模塊讀取并顯示MNIST手寫數(shù)據(jù)集中的圖像,若需要顯示灰度圖
    2024-10-10
  • 如何在Pycharm中制作自己的爬蟲代碼模板

    如何在Pycharm中制作自己的爬蟲代碼模板

    當(dāng)有很多個(gè)個(gè)網(wǎng)站想要爬時(shí),每個(gè)爬蟲的代碼不一樣,但有某種聯(lián)系,這個(gè)時(shí)候可以抽出一部分通用的代碼制成模板,減少代碼工作量。本文將具體介紹如何實(shí)現(xiàn)這一模板,需要的可以參考一下
    2021-12-12
  • Python3解決棋盤覆蓋問題的方法示例

    Python3解決棋盤覆蓋問題的方法示例

    這篇文章主要介紹了Python3解決棋盤覆蓋問題的方法,簡單描述了棋盤覆蓋問題的概念、原理及Python相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • python統(tǒng)計(jì)RGB圖片某像素的個(gè)數(shù)案例

    python統(tǒng)計(jì)RGB圖片某像素的個(gè)數(shù)案例

    這篇文章主要介紹了python統(tǒng)計(jì)RGB圖片某像素的個(gè)數(shù)案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • python用quad、dblquad實(shí)現(xiàn)一維二維積分的實(shí)例詳解

    python用quad、dblquad實(shí)現(xiàn)一維二維積分的實(shí)例詳解

    今天小編大家分享一篇python用quad、dblquad實(shí)現(xiàn)一維二維積分的實(shí)例詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • python小數(shù)字符串轉(zhuǎn)數(shù)字的五種方法

    python小數(shù)字符串轉(zhuǎn)數(shù)字的五種方法

    本文主要介紹了python小數(shù)字符串轉(zhuǎn)數(shù)字的五種方法,根據(jù)具體需求選擇合適的方法進(jìn)行小數(shù)字符串轉(zhuǎn)數(shù)字,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評(píng)論

巴东县| 清镇市| 贡嘎县| 漳平市| 新绛县| 高安市| 健康| 南平市| 崇阳县| 宝鸡市| 汽车| 汉川市| 津市市| 沅江市| 手机| 乐山市| 重庆市| 宁蒗| 汾阳市| 苗栗县| 乌兰察布市| 福贡县| 田东县| 南阳市| 崇信县| 潜江市| 南开区| 苍南县| 武邑县| 荣昌县| 蒲城县| 临海市| 宜良县| 甘德县| 伊川县| 冷水江市| 湖口县| 都江堰市| 永嘉县| 满城县| 新沂市|