Python3學習筆記(二)

好久沒更新了呀,Python的學習可不能落下!??

面向對象編程

面向對象設計思想:抽象出類(Class),根據類創建實例(Instance)。
面向對象的三大特點:封裝,繼承,多態。

  1. 類和實例:

    • 類的定義:class Student(object): pass Student類繼承了object
    • 創建實例:yzl = Student() , 創建實例后,可以自由的給實例綁定屬性yzl.age = 18, 僅對本實例有效
    • 類的方法定義:def __init__(self, name, age):, 第一個變量必須是self, 但不用傳,表示此實例變量。
  2. 訪問限制:以__開頭的是私有變量,外部訪問不到(但其實可以訪問到,只是Python解釋器把私有變量換了個名字,比如_Student__name,以_開頭的雖然可以訪問,但也要當做私有變量,不要輕易訪問。總之,Python本身沒有任何機制阻止你干壞事,一切全靠自覺。

    class Student(object):
    
    def __init__(self, name, score):
        self.__name = name
        self.__score = score
    
    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))
    
  3. 繼承與多態:對于靜態語言,比如Java,一個函數的入參類型必須是確定的,而對于動態語言,只要file-like object即可. 鴨子類型:一個對象只要“看起來像鴨子,走起路來像鴨子”,那它就可以被看做是鴨子。
    只要whatever有run()方法就可以。

    def run_twice(whatever):
            whatever.run()
    
  4. 獲取對象信息:

    • type() 判斷對象類型 type(123): <class 'int'>
    • isinstance() 判斷一個對象是否是某種類型 isinstance('abc', str): True
    • dir() 獲取一個對象的所有屬性和方法,它返回一個包含字符串的list
    • hasattr(obj, 'x') 獲取屬性 setattr(obj, 'y', 19) 設置屬性,注意:只有在不知道對象信息的時候,我們才會去獲取對象信息
  5. 實例屬性和類屬性:不通過__init__()構造,直接在class里定義屬性的是類屬性。實例屬性和類屬性名字不要一樣,否則類屬性在當前實例會被覆蓋掉。

  6. 限制實例的屬性:__slots__ = ('name', 'age') , 定義一個__slots__ 限制類的實例屬性只能在tuple里,否則將報AttributeError錯誤,注意:__slots__只作用于當前類實例,對子類不起作用,若子類也定義了slots,則還要加上父類的slots。

  7. @property : 相當于 getter,@name.setter : 相當于 setter,這兩個decorator的目的是讓方法變為屬性(調用方法生成了屬性),可以寫出更簡短的代碼,同時保證對參數進行必要性的檢查。

    class Screen(object):
        @property
        def width(self):
            return self.__width
    
        @width.setter
        def width(self, w):
            self.__width = w
    
    s = Screen()
    print(dir(s))  # 結果為: ['__class__', '__delattr__', '__dict__', ...]
    s.width = 1
    print(dir(s))  # 結果為: ['_Screen__width', '__class__', '__delattr__', '__dict__', ...]
    
  8. 多繼承:Python支持多繼承,class class Dog(Mammal, Runnable):

  9. 定制類:重寫class的函數,使之符合我們的需求,以下是常用的定制類:

    • __str__ : 自定義打印實例,變量調用的是__repr__

      class Student(object):
          def __init__(self, name):
              self.name = name
          def __str__(self):
              return 'Student object (name=%s)' % self.name
          __repr__ = __str__
      
    • __iter__: 返回一個迭代對象,通過__next()__方法循環獲取下一個值,知道遇到StopIteration錯誤時推出循環

      class Fib(object):
         def __init__(self):
             self.a, self.b = 0, 1 # 初始化兩個計數器a,b
      
         def __iter__(self):
             return self # 實例本身就是迭代對象,故返回自己
      
         def __next__(self):
             self.a, self.b = self.b, self.a + self.b # 計算下一個值
             if self.a > 100000: # 退出循環的條件
                 raise StopIteration();
             return self.a # 返回下一個值
      
    • __getitem__: 按照下標或切片取出元素

      # 重寫__getitem__ 支持索引和切片
      class Fib(object):
          def __getitem__(self, n):
              if isinstance(n, int):  # n是索引
                  a, b = 1, 1
                  for x in range(n):
                      a, b = b, a + b
                  return a
              if isinstance(n, slice):  # n是切片
                  start = n.start
                  stop = n.stop
                  if start is None:
                      start = 0
                  a, b = 1, 1
                  L = []
                  for x in range(stop):
                      if x >= start:
                          L.append(a)
                      a, b = b, a + b
                  return L
      
      print(Fib()[9])
      print(Fib()[:10])
      
    • __getattr__: 動態返回一個屬性, 可以寫一個鏈式調用

      def __getattr__(self, path):
         return Chain('%s/%s' % (self._path, path))
      
    • __call__: 直接在實例本身上調用, 通過callable()函數,可以判斷一個對象是否是“可調用”對象。

      class Student(object):
          def __init__(self, name):
              self.name = name
      
          def __call__(self):
              print('My name is %s.' % self.name)
      
      s = Student('DreamYoung')
      if callable(s):
          s()  # self參數不要傳入    
      
  10. 枚舉類:Enum 枚舉類,把一組相關常量定義在一個class中,class不可變,成員可直接比較

    from enum import Enum, unique
    
    @unique  # @unique裝飾器用于檢查有沒有重復值
    class Weekday(Enum):
        Sun = 0  # Sun的value被設定為0
        Mon = 1, 2
        Tue = 2
    
    print(Weekday.Sun)          # Weekday.Sun
    print(Weekday.Sun.value)    # 0
    print(Weekday.Mon.value)    # (1, 2)
    print(Weekday(2))           # Weekday.Tue
    print(Weekday['Tue'])       # Weekday.Tue
    print(Weekday['Tue'].value) # 2
    

    可見,既可以用成員名稱引用枚舉常量,又可以直接根據value的值獲得枚舉常量

  11. 元類:Python的class的定義是運行時創建的,創建的方法就是使用type()函數!type()函數既可以返回一個對象的類型,又可以創建出新的類型,無需使用class關鍵字。

    def fun(self, name='DreamYoung'):
        print('Hello, ' + name)
        
    Hello = type('Hello', (object,), dict(hello=fun))  # 創建Hello class
    
    h = Hello()
    h.hello()
    

    type()函數需要三個參數:函數名稱,繼承的父類集合(tuple),方法名綁定的函數。
    Python創建類也是掃一下class關鍵字,然后通過type創建出來類。
    如果要控制類的行為,可以使用元類?metaclass,可以把類理解為metaclass創建的實例。 先定義metaclass,就可以創建類,最后創建實例。metaclass暫時不會用到,如果需要深入了解,可以參考這篇文章

錯誤、調試和測試

  1. 錯誤:Python內置了try...except...finally...用于捕獲異常,所有的異常都繼承自BaseException, 查看異常繼承關系

    注意:

    • except可以有多個,多個except異常 父類會覆蓋子類的異常, except后可以跟else
    • finally在最后執行,可以不寫
    • 可以使用logging模塊記錄日志,通過查看調用堆棧,定位排查錯誤

    寫法:

    try:
        print(1/0)
    except ZeroDivisionError as e:
        logging.exception(e)
    else:
        print('else')
    finally:
        print('finally')
    
  2. 調試:要想調試起來爽,要善于使用logging

    logging有debug、info、warning、error幾個級別,通過:

    import logging
    logging.basicConfig(level=logging.INFO) # info級別日志,debug日志不會顯示
    

    指定當前模塊的日志級別,logging的好處是通過簡單的配置,日志可以輸出到文件等等

  3. 單元測試:編寫單元測試需要引入unittest模塊,并編寫一個從unittest.TestCase繼承測試類。
    注意,測試方法必須以test開頭(test_xxx()),否則在測試時不會被執行。unittest提供了很多內置條件的判斷,比如:assertEqual()assertRaises()等等 用于判斷輸出值是否是我們的期望值。

    運行前與運行后:編寫兩個特殊的方法setUp()tearDown(),在每個單元測試方法執行之前執行setUp(),執行之后執行tearDown()。這個用處大大的,比如可以在setUp()方法連接測試庫,tearDown()方法關閉連接。

    運行單元測試有兩種方法:

    1. 加上兩行代碼,這樣可以當做正常的Python腳步運行:

      if __name__ == '__main__':
          unittest.main()
      
    2. (薦)通過命令行參數直接運行單元測試 :可以批量執行單元測試

      $ python3 -m unittest my_test1.py my_test2.py
      
  4. 文檔測試:Python的很多官方文檔都是示例代碼,通過doctest模塊,可以提前并執行文檔注釋代碼。
    比如就絕對值的函數abs()寫上這樣的注釋:

    def abs(n):
        """
        Function to get absolute value of number.
    
        Example:
    
        >>> abs('')
        Traceback (most recent call last):
            ...
        TypeError: unorderable types: str() >= int()
        >>> abs(1)
        1
        >>> abs(-1)
        1
        >>> abs(0)
        0
        """
        return n if n >= 0 else (-n + 1)  # 正確的代碼應為: return n if n >= 0 else (-n)
    
    if __name__ == '__main__':
        import doctest
    
        doctest.testmod()
    

    會得到以下輸出:


File "xxxx/demo/dream/young/python/Test.py", line 13, in main.abs
Failed example:
abs(-1)
Expected:
1
Got:
2


1 items had failures:
1 of 4 in main.abs
Test Failed 1 failures.


如果沒有輸出任何信息,說明注釋代碼沒有錯誤。注意:當模塊正常導入時,doctest不會被執行。只有在命令行直接運行時,才執行doctest。所以,不必擔心doctest會在非測試環境下執行。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容