<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Python數據模型及Pythonic編程

      Python作為一種多范式語言,它的很多語言特性都能從其他語言上找到參照,但是Python依然形成了一套自己的“Python 風格”(Pythonic)。這種Pythonic風格完全體現在 Python 的數據模型上,而數據模型中的元接口(指那些名字以兩個下劃線開頭,以兩個下劃線結尾的特殊方法,例如 __getitem__),就是編寫地道的Python代碼的秘密所在。這種基于元接口實現的設計模式,也叫鴨子類型(duck typing)。

      鴨子類型指的是對象的類型無關緊要,只要實現了特定的接口即可。忽略對象的真正類型,轉而關注對象有沒有實現所需的方法、簽名和語義。Python的數據模型都支持鴨子類型,鴨子類型也是地道Python編程鼓勵的風格,所以如果覺得自己想創建新的抽象基類,先試著通過常規的鴨子類型來解決問題。

      數據模型其實是對 Python 框架的描述,它規范了這門語言自身構建模塊的接口,這些模塊包括類、函數、序列、迭代器、上下文管理器等。

       

      得益于 Python 數據模型,自定義類的行為可以像內置類型那樣自然。實現如此自然的行為,靠的不是繼承,而是元接口。Python給類設計了大量的元接口,具體請參看Python 語言參考手冊中的“Data Model”章節。下面是一些類的元接口的展示。

      """
          >>> v1 = Vector2d(3, 4)
      
          通過元接口__iter__支持拆包
          >>> x, y = v1
          >>> x, y
          (3.0, 4.0)
      
          通過元接口__repr__支持字面量表示和repr函數
          >>> v1
          Vector2d(3.0, 4.0)
          >>> v1_clone = eval(repr(v1))
          >>> v1 == v1_clone
          True
      
          通過元接口__str__支持print函數
          >>> print(v1)
          (3.0, 4.0)
      
          通過元接口__bytes__支持bytes函數
          >>> octets = bytes(v1)
          >>> octets
          b'd\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@'
      
          通過元接口__abs__支持abs函數
          >>> abs(v1)
          5.0
      
          通過元接口__bool__支持bool函數
          >>> bool(v1), bool(Vector2d(0, 0))
          (True, False)
      
          通過property支持可讀屬性
          >>> v1.x, v1.y
          (3.0, 4.0)
          >>> v1.x = 123
          Traceback (most recent call last):
            ...
          AttributeError: can't set attribute
      
          通過__hash__支持對象可散列,支持dict、set等函數
          >>> hash(v1)
          7
          >>> set(v1)
          {3.0, 4.0}
          >>> {v1: 'point1'}
          {Vector2d(3.0, 4.0): 'point1'}
      
      """
      
      from array import array
      import math
      
      class Vector2d:
          typecode = 'd'
      
          def __init__(self, x, y):
              self.__x = float(x) 
              self.__y = float(y)
      
          @property
          def x(self):
              return self.__x
      
          @property
          def y(self):
              return self.__y
      
          def __iter__(self):
              return (i for i in (self.x, self.y))
      
          def __repr__(self):
              class_name = type(self).__name__
              return '{}({!r}, {!r})'.format(class_name, *self)
      
          def __str__(self):
              return str(tuple(self))
      
          def __bytes__(self):
              return (bytes([ord(self.typecode)]) +
                      bytes(array(self.typecode, self)))
      
          def __eq__(self, other):
              return tuple(self) == tuple(other)
      
          def __hash__(self):
              return hash(self.x) ^ hash(self.y)
      
          def __abs__(self):
              return math.hypot(self.x, self.y)
      
          def __bool__(self):
              return bool(abs(self))

      函數

       Python中一切皆對象,函數也不例外,而且Python中的函數還是一等對象。函數可以理解為一種可調用對象語法糖。

      可調用對象的元接口是__call__。如果一個類定義了 __call__ 方法,那么它的實例可以作為函數調用。示例如下。

      """
      >>> pickcard = Cards(range(52))
      >>> pickcard()
      51
      >>> pickcard()
      50
      >>> callable(pickcard)
      True
      """
      class Cards:
          def __init__(self, items):
              self._items = list(items)
      
          def __call__(self):
              return self._items.pop()

       

      序列

      Python 的序列數據模型的元接口很多,但是對象只需要實現 __len__ 和 __getitem__ 兩個方法,就能用在絕大部分期待序列的地方,如迭代,[]運算符、切片、for i in 等操作。示例如下:

      """
      >>> poker = Poker()
      
      支持len運算
      >>> len(poker)
      52
      
      支持[]運算
      >>> poker[0]
      Card(rank='2', suit='spades')
      >>> poker[-1]
      Card(rank='A', suit='hearts')
      
      支持切片運算
      >>> poker[12::13]
      [Card(rank='A', suit='spades'), Card(rank='A', suit='diamonds'), Card(rank='A', suit='clubs'), Card(rank='A', suit='hearts')]
      
      支持 for i in 運算
      >>> for card in poker: print(card)  # doctest: +ELLIPSIS
      ...
      Card(rank='2', suit='spades')
      Card(rank='3', suit='spades')
      Card(rank='4', suit='spades')
      ...
      
      支持 in 運算
      >>> Card('7', 'hearts') in poker
      True
      
      """
      
      import collections
      
      Card = collections.namedtuple('Card', ['rank', 'suit'])
      class Poker:
          ranks = [str(n) for n in range(2, 11)] + list('JQKA')
          suits = 'spades diamonds clubs hearts'.split()
          def __init__(self):
              self._cards = [Card(rank, suit) for suit in self.suits
                                              for rank in self.ranks]
          def __len__(self):
              return len(self._cards)
          def __getitem__(self, position):
              return self._cards[position] 

      從測試用例上可以看出它具有序列所有特性,即便它是 object 的子類也無妨。因為它的行為像序列,那我們就可以說它是序列。

      迭代

       Python中,可迭代對象的元接口是__iter__。迭代器可以從可迭代的對象中獲取,__iter__和__next__是它的2個主要的元接口。__iter__ 方法使對象支持迭代,__next__ 方法返回序列中的下一個元素。如果沒有元素了,那么拋出 StopIteration 異常。

      迭代器可以迭代,但是可迭代的對象不是迭代器,也一定不能是自身的迭代器。也就是說,可迭代的對象必須實現 __iter__ 方法,但不能實現 __next__ 方法。

      只要實現__iter__接口的對象,就是迭代鴨子類型,自然就支持所有的迭代運算。示例如下:

      """
      >>> s = Sentence('hello world')
      >>> s
      Sentence('hello world')
      
      支持迭代list運算
      >>> list(s)
      ['hello', 'world']
      
      獲取迭代器
      >>> it = iter(s)
      
      支持迭代器next運算
      >>> next(it)
      'hello'
      >>> next(it)
      'world'
      >>> next(it)
      Traceback (most recent call last):
        ...
      StopIteration
      
      支持迭代for運算
      >>> for w in s: print(w)
      hello
      world
      """
      
      import re
      import reprlib
      
      RE_WORD = re.compile('\w+')
      
      class Sentence:
      
          def __init__(self, text):
              self.text = text
      
          def __repr__(self):
              return 'Sentence(%s)' % reprlib.repr(self.text)
      
          def __iter__(self):
              word_iter = RE_WORD.finditer(self.text)  
              return SentenceIter(word_iter)  
      
      
      class SentenceIter():
      
          def __init__(self, word_iter):
              self.word_iter = word_iter  
      
          def __next__(self):
              match = next(self.word_iter)  
              return match.group()  
      
          def __iter__(self):
              return self

      上面這個例子中,可迭代對象Sentence通過定義迭代器SentenceIter的方式實現。更Pythonic的做法是通過生成器yield來實現。下面是一個示例,能通過上面的所有測試用例,但代碼更加精簡。

      RE_WORD = re.compile('\w+')
      
      class Sentence:
      
          def __init__(self, text):
              self.text = text 
      
          def __repr__(self):
              return 'Sentence(%s)' % reprlib.repr(self.text)
      
          def __iter__(self):
              for match in RE_WORD.finditer(self.text):
                  yield match.group()  

      上下文管理器

       Python的with關鍵字是上下文管理器語法糖,上下文管理器協議包含 __enter__ 和 __exit__ 兩個方法。with 語句開始運行時,會在上下文管理器對象上調用 __enter__ 方法。with 語句運行結束后,會在上下文管理器對象上調用 __exit__ 方法,以此扮演 finally 子句的角色。可以看出,上下文管理器簡化了 try/finally 模式。下面是一個示例。

      """
      ReversePrint對象的上下文管理,進入with塊后,標準輸出反序打印,
      退出with塊后,標準輸出恢復正常狀態。
      >>> with ReversePrint() as what:
      ...      print('Hello world!')
      !dlrow olleH
      >>> print('Hello world!') 
      Hello world!
      
      """
      
      class ReversePrint:
      
          def __enter__(self):
              import sys
              self.original_write = sys.stdout.write
              sys.stdout.write = self.reverse_write
              return 'JABBERWOCKY'
      
          def reverse_write(self, text):
              self.original_write(text[::-1])
      
          def __exit__(self, exc_type, exc_value, traceback):
              import sys
              sys.stdout.write = self.original_write
              if exc_type is ZeroDivisionError:
                  print('Please DO NOT divide by zero!')
                  return True

       

      posted @ 2019-01-11 18:41  wahaha02  閱讀(696)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲理论在线A中文字幕| 景泰县| 四虎精品视频永久免费| 日韩伦人妻无码| 欧洲美女黑人粗性暴交视频| 亚洲综合91社区精品福利| 黄色亚洲一区二区三区四区| 国产亚洲精品AA片在线播放天 | 人妻少妇偷人一区二区| 亚洲欧美中文字幕日韩一区二区| 国产美女深夜福利在线一| 国产成人精品区一区二区| 亚洲精品乱码久久久久久蜜桃不卡| 亚洲自偷自拍熟女另类| 国产精品美女一区二三区| 久久久久久久久18禁秘| 一区二区三区av天堂| 精品国产乱码久久久久APP下载| 欧美日韩精品一区二区视频| 色www视频永久免费| 日韩乱码人妻无码中文字幕视频| 日99久9在线 | 免费| 亚洲精品久久国产高清| 亚洲18禁一区二区三区| 亚洲国产成人午夜在线一区| 国产精品小仙女自拍视频| 久久久久久久一线毛片| 安溪县| 日本久久久久亚洲中字幕| 四虎国产精品永久入口| 日本丰满熟妇videossexhd| 久久亚洲精品中文字幕波多野结衣| 国内极度色诱视频网站| 日本国产一区二区三区在线观看| 无码抽搐高潮喷水流白浆| 人妻性奴波多野结衣无码| 26uuu另类亚洲欧美日本| 99久久国产宗和精品1上映| 亚洲精品自拍在线视频| 亚洲AⅤ天堂AV天堂无码| 亚洲成av人片一区二区|