Python3學(xué)習(xí)筆記(二)

好久沒更新了呀,Python的學(xué)習(xí)可不能落下你画!??

面向?qū)ο缶幊?/h2>

面向?qū)ο笤O(shè)計思想:抽象出類(Class)抵碟,根據(jù)類創(chuàng)建實例(Instance)桃漾。
面向?qū)ο蟮娜筇攸c:封裝,繼承拟逮,多態(tài)撬统。

  1. 類和實例:

    • 類的定義:class Student(object): pass Student類繼承了object
    • 創(chuàng)建實例:yzl = Student() , 創(chuàng)建實例后,可以自由的給實例綁定屬性yzl.age = 18, 僅對本實例有效
    • 類的方法定義:def __init__(self, name, age):, 第一個變量必須是self, 但不用傳敦迄,表示此實例變量恋追。
  2. 訪問限制:以__開頭的是私有變量,外部訪問不到(但其實可以訪問到罚屋,只是Python解釋器把私有變量換了個名字苦囱,比如_Student__name,以_開頭的雖然可以訪問脾猛,但也要當(dāng)做私有變量撕彤,不要輕易訪問∶退總之羹铅,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. 繼承與多態(tài):對于靜態(tài)語言睦裳,比如Java造锅,一個函數(shù)的入?yún)㈩愋捅仨毷谴_定的撼唾,而對于動態(tài)語言,只要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) 設(shè)置屬性,注意:只有在不知道對象信息的時候深夯,我們才會去獲取對象信息
  5. 實例屬性和類屬性:不通過__init__()構(gòu)造抖格,直接在class里定義屬性的是類屬性。實例屬性和類屬性名字不要一樣咕晋,否則類屬性在當(dāng)前實例會被覆蓋掉雹拄。

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

  7. @property : 相當(dāng)于 getter翩肌,@name.setter : 相當(dāng)于 setter,這兩個decorator的目的是讓方法變?yōu)閷傩?調(diào)用方法生成了屬性)禁悠,可以寫出更簡短的代碼念祭,同時保證對參數(shù)進行必要性的檢查。

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

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

    • __str__ : 自定義打印實例祝钢,變量調(diào)用的是__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()__方法循環(huán)獲取下一個值,知道遇到StopIteration錯誤時推出循環(huán)

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

      # 重寫__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__: 動態(tài)返回一個屬性, 可以寫一個鏈?zhǔn)秸{(diào)用

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

      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參數(shù)不要傳入    
      
  10. 枚舉類:Enum 枚舉類灾常,把一組相關(guān)常量定義在一個class中,class不可變铃拇,成員可直接比較

    from enum import Enum, unique
    
    @unique  # @unique裝飾器用于檢查有沒有重復(fù)值
    class Weekday(Enum):
        Sun = 0  # Sun的value被設(shè)定為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
    

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

  11. 元類:Python的class的定義是運行時創(chuàng)建的慷荔,創(chuàng)建的方法就是使用type()函數(shù)雕什!type()函數(shù)既可以返回一個對象的類型,又可以創(chuàng)建出新的類型显晶,無需使用class關(guān)鍵字贷岸。

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

    type()函數(shù)需要三個參數(shù):函數(shù)名稱,繼承的父類集合(tuple)磷雇,方法名綁定的函數(shù)偿警。
    Python創(chuàng)建類也是掃一下class關(guān)鍵字,然后通過type創(chuàng)建出來類唯笙。
    如果要控制類的行為螟蒸,可以使用元類?metaclass,可以把類理解為metaclass創(chuàng)建的實例崩掘。 先定義metaclass七嫌,就可以創(chuàng)建類,最后創(chuàng)建實例呢堰。metaclass暫時不會用到抄瑟,如果需要深入了解,可以參考這篇文章

錯誤、調(diào)試和測試

  1. 錯誤:Python內(nèi)置了try...except...finally...用于捕獲異常皮假,所有的異常都繼承自BaseException, 查看異常繼承關(guān)系

    注意:

    • except可以有多個鞋拟,多個except異常 父類會覆蓋子類的異常, except后可以跟else
    • finally在最后執(zhí)行惹资,可以不寫
    • 可以使用logging模塊記錄日志贺纲,通過查看調(diào)用堆棧,定位排查錯誤

    寫法:

    try:
        print(1/0)
    except ZeroDivisionError as e:
        logging.exception(e)
    else:
        print('else')
    finally:
        print('finally')
    
  2. 調(diào)試:要想調(diào)試起來爽褪测,要善于使用logging猴誊!

    logging有debug、info侮措、warning懈叹、error幾個級別,通過:

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

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

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

    運行前與運行后:編寫兩個特殊的方法setUp()tearDown(),在每個單元測試方法執(zhí)行之前執(zhí)行setUp()肛根,執(zhí)行之后執(zhí)行tearDown()辫塌。這個用處大大的漏策,比如可以在setUp()方法連接測試庫派哲,tearDown()方法關(guān)閉連接。

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

    1. 加上兩行代碼掺喻,這樣可以當(dāng)做正常的Python腳步運行:

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

      $ python3 -m unittest my_test1.py my_test2.py
      
  4. 文檔測試:Python的很多官方文檔都是示例代碼芭届,通過doctest模塊,可以提前并執(zhí)行文檔注釋代碼感耙。
    比如就絕對值的函數(shù)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)  # 正確的代碼應(yīng)為: 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.


如果沒有輸出任何信息褂乍,說明注釋代碼沒有錯誤。注意:當(dāng)模塊正常導(dǎo)入時即硼,doctest不會被執(zhí)行逃片。只有在命令行直接運行時,才執(zhí)行doctest只酥。所以褥实,不必?fù)?dān)心doctest會在非測試環(huán)境下執(zhí)行呀狼。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市损离,隨后出現(xiàn)的幾起案子哥艇,更是在濱河造成了極大的恐慌,老刑警劉巖僻澎,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件貌踏,死亡現(xiàn)場離奇詭異,居然都是意外死亡窟勃,警方通過查閱死者的電腦和手機祖乳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秉氧,“玉大人凡资,你說我怎么就攤上這事∶耍” “怎么了隙赁?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梆暖。 經(jīng)常有香客問我伞访,道長,這世上最難降的妖魔是什么轰驳? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任厚掷,我火速辦了婚禮,結(jié)果婚禮上级解,老公的妹妹穿的比我還像新娘冒黑。我一直安慰自己,他們只是感情好勤哗,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布抡爹。 她就那樣靜靜地躺著,像睡著了一般芒划。 火紅的嫁衣襯著肌膚如雪冬竟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天民逼,我揣著相機與錄音泵殴,去河邊找鬼。 笑死拼苍,一個胖子當(dāng)著我的面吹牛笑诅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼吆你,長吁一口氣:“原來是場噩夢啊……” “哼同蜻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起早处,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤湾蔓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后砌梆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體默责,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年咸包,在試婚紗的時候發(fā)現(xiàn)自己被綠了桃序。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡烂瘫,死狀恐怖媒熊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坟比,我是刑警寧澤芦鳍,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站葛账,受9級特大地震影響柠衅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜籍琳,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一菲宴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧趋急,春花似錦喝峦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闻丑,卻和暖如春漩怎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗦嗡。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饭玲,地道東北人侥祭。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矮冬。 傳聞我的和親對象是個殘疾皇子谈宛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容