Python 一些小技巧和注意事項(xiàng)

  1. 快速反轉(zhuǎn):a = [1,2,3,4] b = 'abcdefg'

     a[::-1] ===> [4,3,2,1], b[::-1]===> 'gfedcba'
     正常的代碼: list(reverse(a)),  list(reversed(b))
    
  2. 使用with語(yǔ)句打開(kāi)一個(gè)文件,可以避免文件讀取失敗時(shí),文件未關(guān)閉的情況

    with open(path, 'r') as f:
        do_sth_with(f)
    
  3. 格式化輸出的時(shí)候可以使用空格占位符

    >>> dict = {'name': 'sdfsdf', 'age': 'ddd', 'sex': 'man'}
    >>> print(f"{dict['name']:10}-----dfk")
    >>> prrint("{0:10}----{1:8}" % (dict['name'], dict['age']))
    >>> sdfsdf    -----dfk
    
  4. 在for 或是 while 循環(huán)中使用else的時(shí)候需要注意他的使用情況,

    • 在循環(huán)中使用了 break的,那么else不會(huì)被執(zhí)行。
    • 如果循環(huán)的數(shù)據(jù)時(shí)空的,回立刻執(zhí)行else語(yǔ)句
    • 如果初始循環(huán)的while語(yǔ)句是false,那么else也會(huì)立馬執(zhí)行
  5. 了解如何在閉包里面使用外圍作用域的變量

    可以使用關(guān)鍵字 nonlocal來(lái)進(jìn)行注明:
    def sort_priority(nums, group):
        found = False
        def helper(x):
            nonlocal found
            if x in group:
                found = True
                return (0, x)
            return (1, x)
    
        nums.sort(key=helper)
    
        >>> 運(yùn)行結(jié)果如果不添加nonlocal,found返回的結(jié)果是 False,因?yàn)樗情]包里面的變量(不可變的變量)相當(dāng)于是在閉包里面新建來(lái)一個(gè)變量
    
        Python2 沒(méi)有nonlocal關(guān)鍵字,但是可以使用list數(shù)據(jù)類(lèi)型類(lèi)實(shí)現(xiàn)該功能
        def sort_priority(nums, group):
            found = [False]
            def helper(x):
                if x in group:
                    found[0] = True
                    return (0, x)
                return (1, x)
    
        因?yàn)檫@里的found是一個(gè)可變對(duì)象(列表)滿(mǎn)足符合條件
    
    
  6. 設(shè)置方法默認(rèn)值的時(shí)候,一定要使用None來(lái)設(shè)置,因?yàn)槟J(rèn)值只會(huì)在方法被加載的第一次里面調(diào)用,生成,后面調(diào)用方法的時(shí)候,其實(shí)是使用之前已經(jīng)生成的默認(rèn)值。這樣回會(huì)出現(xiàn)很奇怪的問(wèn)題的。

    def decode(data, default={}):
        try:
            return json.loads(data)
        except ValueError:
            return default
    
    boo = decode("boo")
    boo['boo'] = 'boo'
    far = decode('far')
    far['far'] = far
    
    print(boo)  ==>  {"boo": "boo", "far": "far"}
    print(far)  ==>  {"boo": "boo", "far": "far"}
    
    兩次輸出的結(jié)果是一樣的,這是因?yàn)樵诜椒虞d的時(shí)候,返回的是同一個(gè)默認(rèn)值。
    
  7. 盡量使用輔助類(lèi)來(lái)維護(hù)程序的狀態(tài),而不是使用字典或是元組

  8. 使用函數(shù)充當(dāng)API掛鉤,在方法參數(shù)中,應(yīng)該傳遞一個(gè)方法,而不是類(lèi)的實(shí)例。

  9. 可以定義新的類(lèi)來(lái)記錄函數(shù)的狀態(tài),并且新的類(lèi)需要實(shí)現(xiàn)call方法。

  10. 總是使用內(nèi)置的 super函數(shù) 來(lái)初始化父類(lèi)。

  11. 使用mix-in 組建實(shí)現(xiàn)的效果,就不要使用多繼承去實(shí)現(xiàn)。

  12. 多使用public 少用 private

    Python 會(huì)對(duì)私有屬性的名稱(chēng)做一些簡(jiǎn)單的變換,以保證private的字段的私密性,私有屬性字段的真實(shí)姓稱(chēng)是: _ClassName__privateName
    
    def MyParentObject(object):
        def __init__(self):
            self.__private_field = 7
    
    def MyChildrenObject(MyParentObject):
        def get_private_field(self):
            return self.__private_filed
    
    baz = MyChildrenObject()
    baz.get_private_field()
    ===>> 這里是回報(bào)錯(cuò)的,因?yàn)樵谧宇?lèi)里面不能直接訪問(wèn)父類(lèi)的私有實(shí)例變量,因?yàn)樯厦嬲f(shuō)的,私有變量實(shí)際名稱(chēng)是會(huì)被更改的,因此在子類(lèi)里面調(diào)用父類(lèi)的私有變量其實(shí)是不存在的。
    如果了解私有變量的變量名變更規(guī)則,那么在任何地方都可以調(diào)用私有變量了。
    
    print(baz._MyParentObject__private_field)
    ====>   7
    
  13. camelCase 轉(zhuǎn)換成 snake_case

    def camel_to_snake(name): 
    """
    A function that converts camelCase to snake_case.
    Referred from: https://stackoverflow.com/questions/1175208/elegant-python-function-to-convert-camelcase-to-snake-case
    """
    import re
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
    
    class SnakeCaseMetaclass(type):
        def __new__(snakecase_metaclass, future_class_name,
                    future_class_parents, future_class_attr): 
            snakecase_attrs = {}
            for name, val in future_class_attr.items(): 
                snakecase_attrs[camel_to_snake(name)] = val
            return type(future_class_name, future_class_parents,
                        snakecase_attrs)
    
    您可能想知道我們?cè)谶@里為什么使用 __new__ 而不是 __init__。__new__ 實(shí)際上是創(chuàng)建實(shí)例的第一步。它負(fù)責(zé)返回類(lèi)的新實(shí)例。而在另一方面,__init__ 則不會(huì)返回任何內(nèi)容。它只負(fù)責(zé)在創(chuàng)建實(shí)例后對(duì)其進(jìn)行初始化。請(qǐng)牢記一條簡(jiǎn)單的經(jīng)驗(yàn)法則:當(dāng)需要控制新實(shí)例的創(chuàng)建時(shí)使用 new,而在需要控制新實(shí)例的初始化時(shí)則使用 init。
    
  14. 當(dāng)列表不是首選時(shí)

    • 如果需要存入大量的數(shù)據(jù)時(shí),可以使用數(shù)組(比如要存放1000萬(wàn)個(gè)浮點(diǎn)數(shù),數(shù)組的效率會(huì)高很多,因?yàn)閿?shù)組 里面并不是存放float對(duì)象,而是數(shù)字的機(jī)器翻譯,就是字節(jié)表述)
    • 如果需要對(duì)列表進(jìn)行先進(jìn)先出的操作, deque(雙端隊(duì)列)的速度應(yīng)該會(huì)更快。
  15. 使用dis.dis反匯編函數(shù),可以查看方法的字節(jié)碼運(yùn)行情況。

  16. 從python3.3之后,python解釋器會(huì)在創(chuàng)建str的時(shí)候自動(dòng)計(jì)算為str分配最經(jīng)濟(jì)的內(nèi)存,如果字符都在latin1字符集中?那就使用一個(gè)字節(jié)存儲(chǔ)每個(gè)碼位,否則根據(jù)字符串中的每個(gè)字符,分配 2 或 4 個(gè)字節(jié)存儲(chǔ)每個(gè)碼位。
    詳細(xì)鏈接

  17. 判斷對(duì)象能否被調(diào)用,最好使用內(nèi)置的方法 callable()進(jìn)行判斷。

    [callable(obj) for obj in (len, str, 23)]
    
    ===>>  [True, True, False]
    
  18. python里面 == 比較的是值相等,但是 is not 或是 is 比較的是對(duì)象引用空間分配的內(nèi)存地址是否相等?;蚴强梢允褂?id() 這個(gè)方法判斷兩個(gè)變量指向的對(duì)象是否是同一個(gè)。

    >>> a = {"name": 'MrXi', "age": 27}
    >>> b = {"name": 'MrXi', "age": 27}
    
    >>> a == b
    >>> True
    
    >>> a is not b
    >>> True
    
    >>> id(a)
    >>> id(b)
    
  19. 方法 del不會(huì)刪除對(duì)象,但是會(huì)刪除對(duì)象的引用,從而導(dǎo)致對(duì)象無(wú)法被獲取,產(chǎn)生對(duì)象被刪除的現(xiàn)象。(其實(shí)對(duì)象在長(zhǎng)時(shí)間未被使用的情況下,會(huì)被垃圾回收機(jī)制處理。也會(huì)被刪除)

  20. 變量保存的是引用,因此如下的規(guī)則需要謹(jǐn)記

    • 簡(jiǎn)單的賦值不創(chuàng)建副本
    • 對(duì) += 或是 *= 所做的增量賦值來(lái)說(shuō),如果左邊的變量綁定的是不可變對(duì)象,會(huì)創(chuàng)建新對(duì)象;如果是可變對(duì)象,會(huì)就地修改。
    • 為現(xiàn)有的變量賦予新值,不會(huì)修改之前綁定的變量。這叫重新綁定:現(xiàn)在變量綁定了其他對(duì)象。如果變量是之前那個(gè)對(duì)象的最后一個(gè)引用,對(duì)象會(huì)被當(dāng)作垃圾回收。
    • 函數(shù)的參數(shù)以別名的形式傳遞,這意味著,函數(shù)肯能會(huì)修改通過(guò)參數(shù)傳入的可變對(duì)象,這一行為無(wú)法避免,除非在本地創(chuàng)建副本,或者使用不可變對(duì)象。
    • 使用可變類(lèi)型作為函數(shù)參數(shù)的默認(rèn)值有危險(xiǎn),因?yàn)槿绻偷匦薷牧藚?shù),默認(rèn)值也就變了,這會(huì)影響以后使用默認(rèn)值的調(diào)用。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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