Python經常使用知識點一二

寫在前面

Python是一門解釋型的、動態型的OOP語言,結識Python的這幾年來,其語法的簡潔、結構的條理性深入的吸引了我。下面是我總結出來的一些Python經常使用知識點。html

列表碾平式

需求: 將[[1,2],[3,4]] 轉換爲[1,2,3,4],具體實現有如下幾種方法python

test_list = [[1,2],[3,4]]

1. from itertools import chain
   list(chain.from_iterable(test_list))
   結果:[1, 2, 3, 4]

2. from itertools import chain
   list(chain(*test_list))
   結果:[1, 2, 3, 4]

3. sum(test_list, [])
   結果:[1, 2, 3, 4]

4. [x for y in test_list for x in y]
   結果:[1, 2, 3, 4]

5. 萬能方法(遞歸)
   func = lambda x: [y for t in x for y in func(t)] if type(x) is list else [x]
   func(test_list)
   結果:[1, 2, 3, 4]複製代碼

PS: 項目中,不免會有相似的需求,對於結構嵌套一致的狀況,上述的1,2,3,4方法均可以很好的解決(不建議用for循環嵌套的方式,那是最low的方法,沒有之一);對於結構嵌套不一致的狀況,第5種方法就派上了用場,其採用了遞歸的思想,堪稱萬能的方法,屢試不爽。項目中,你們能夠根據實際應用場景來挑選最適合本身的方法。肚中有糧,心中不慌;你們能夠把上述方法都記下來,以作到有的放矢。web

三目操做符

對於Python的三元表達式,想必你們對if else都不會感到陌生,可是對and or操做想必是另外一種感受了,不過你們對其餘語言的? :應該不會陌生,沒錯,此次的主角and or就和? :有着殊途同歸之妙。ajax

代碼參考:django

1 == 1 and 2 or 3   返回2
1 == 2 and 2 or 3   返回3複製代碼

PS:習慣於if else的同窗偶爾用下and or是否是會給人耳目一新的感受。json

and or 分開來用

  • [x] and 用法以下:
1 and 2 and 3   返回3
1 and 2 and ''   返回''
'' and 2 and 0  返回''
PS:若是都爲真則返回最後一個值,若是其中某些值爲假,則返回第一個爲假的值複製代碼
  • [x] or 用法以下
1 or '' or 0    返回1
'' or 0 or []    返回[]
PS:若是都爲假返回最後一個值,若是其中某些值爲真,則返回第一個爲真的值複製代碼

使用場景:在項目中咱們常常會有這樣的需求,在將一個字典更新以後還想要返回更新後的字典,這是咱們就能夠這樣寫:dic = dic1.update(dic2) or dic1緩存

列表推導式

需求:將[1,2,3]中的每一項都加1bash

good: [x+1 for x in [1,2,3]]
bad:  def add_list(goal_list):
          tmp_list = []
          for x in goal_list:
              tmp_list.append(x+1)複製代碼

PS: 列表推導式底層是用C實現的,其執行速度要比for循環快好多服務器

vars() 用法

代碼參考:app

```
def func(a, b, c):
    print vars()
執行func(1, 2, 3)
輸出:{"a":1,"b":2,"c":3}
PS: vars()的值爲字典,其鍵值對來源於當前做用域的全部變量。
```複製代碼

使用場景:在調用他人接口或方法時,須要將傳入的參數打印以記錄日誌,此刻vars()便派上用場了。

偏函數之partial

代碼示例:

import functools
def add(a, b):
    return a + b
add(4, 2)
    6
plus3 = functools.partial(add, 3)
plus5 = functools.partial(add, 5)
plus3(4)
    7
plus3(7)
    10
plus5(10)
    15複製代碼

實際使用心得:

以前作對象存儲的項目中,我須要同時去調用三個同樣的接口(大部分參數同樣)下面是個人部分代碼,供你們參考

my_thread = functools.partial(myThread, dic, zone_id, start, end, customer_id)
my_thread1 = my_thread("day", "gets", "2")
my_thread1 = my_thread("day", "original_traffic", "3")複製代碼

使用場景:
當咱們須要同時去調用一個函數,而且發現大部分參數一致的時候,即可以採起上述方法,一來代碼簡潔,二來可讀性高。

Python搭建簡易服務

  • Python搭建簡易郵件服務器:python -m smtpd -n -c DebuggingServer localhost:1025
  • Python搭建簡易web服務器:

    • Python2: python -m SimpleHTTPServer port
    • Python3: python -m http.server port
  • Python搭建簡易ftp服務

    pip install pyftpdlib
      python -m pyftpdlib -p 21
      ftp://localhost:21複製代碼

遍歷字典

在項目中遍歷字典是很常見的需求,下面介紹下經常使用的方法並作下比較:

dic = {'name': 'peter', 'age': 27}
1. for key, value in dic.items():
       print key, value
2. for key, value in dic.iteritems():
       print key, value複製代碼

PS:
iteritemsitems的區別在於iteritems採用了生成器的原理,只有在須要的時候纔會把值生成,其之間的區別相似於rangexrangereadlinexreadline

內存管理

Python的內存管理主要分爲引用計數和垃圾回收機制兩大部分,且看下面代碼:

  • [ ] 內存分配:

    a = 1
      b = 1
      a is b      True
      ---------------------
      a = 1000
      b = 1000
      a is b      False複製代碼

    PS: 在Python中,整數和短小的字符,Python都會緩存這些對象,以便重複使用。當咱們建立多個等於1的引用時,其實是讓這些引用指向了同一個對象。

  • [ ] 引用計數:

    在Python中,所謂引用計數(reference count)是指全部指向該對象的引用的總數;

    咱們可使用sys包中的getrefcount(),來查看某個對象的引用計數。須要注意的是,當使用該函數查看某個對象的引用計數時,其實是臨時建立了該對象的一個新的引用,全部使用getrefcount()所獲得的結果,會比指望的值多1。

    from sys import getrefcount
      aa = 'test refcount'
      print(getrefcount(a))
      bb = aa
      print(getrefcount(a))複製代碼

    PS: 因爲上述緣由,兩個getrefcount()將返回2和3,並非指望的1和2.

  • [ ] 引用減小

    引用減小大體分爲兩類:

    • 指向該對象的引用指向了其餘對象

      from sys import getrefcount
      
         aa = 'test refcount'
         bb = aa
         print(getrefcount(aa))      3
      
         bb = 1
         print(getrefcount(aa))      2複製代碼
    • 使用del關鍵字顯示的刪除某個引用

      from sys import getrefcount
      
         aa = 'test refcount'
         bb = aa
         print(getrefcount(aa))      3
      
         del bb
         print(getrefcount(aa))      2複製代碼
  • [ ] 垃圾回收

    不斷的建立對象,若是不及時銷燬的話,那Python的體積會愈來愈大,再大的內存也會有耗完的時候;不用像C語言那樣,須要手動的去管理內存、Python已經幫咱們作好了(Python的垃圾回收機制),你只須要去關心你的業務邏輯便可,其餘的都交給Python來處理。

    從原理上講,當Python中某個對象的引用計數降爲0時,該對象就應該被回收。可是頻繁的啓動垃圾回收機制畢竟是個很耗時的問題;所以Python只有在特定條件下(當Python中被分配對象和取消分配對象的次數之間的差值達到某個閾值時),Python會自動啓動垃圾回收機制。

    咱們能夠經過gc模塊的get_threshold()方法,查看該閾值:

    import gc
      print(gc.get_threshold())複製代碼

    該方法會返回(700, 10, 10),後面的倆10是與分代回收相關的,稍後講解。700即是垃圾回收機制啓動的閾值。能夠經過gc模塊中的set_threshold()方法從新設定該值。

    固然了,咱們也能夠手動啓動垃圾回收機制,使用gc.collect()便可。

  • [ ] 分代回收

    Python同時採用了分代回收的機制,設想一下:存活越久的對象、越不多是垃圾對象。程序在運行時,每每會產生大量的臨時對象,程序結束以後,這些臨時對象的生命週期也就隨之告一段落。但有一些對象會被長期佔用,垃圾回收機制在啓動的時候會減小掃描到他們的頻率。

    Python將全部對象分爲0,1,2三代。全部新建立的對象都是0代,當垃圾回收機制在啓動屢次0代機制並掃描到他們的時候,這些對象若是依然存活在內存的話,他們就會被納入下一代對象,以此類推。

    剛纔上面所提到的(700, 10, 10)三個參數後面的倆10所表明的意思是:每10次0代垃圾回收,會配合1次1代的垃圾回收;而每10次1代的垃圾回收會配合1次的2代垃圾回收。

    固然咱們一樣可使用set_threshold()來調整此策略的比例,好比對1代對象進行更頻繁的掃描。

    import gc
      gc.set_threshold(700, 5, 10)複製代碼

新式類、經典類

  • [ ] 新式類: 顯示的繼承了object的類

    class A(object):
          attr = 1
    
      class B(A):
          pass
    
      class C(A):
          attr = 3
    
      class D(B, C):
          pass
    
      if __name__ == '__main__':
          d = D()
          print 'attr = ', d.attr     # attr = 3複製代碼
  • [ ] 經典類:沒有繼承自object的類

    class A():
          attr = 1
    
      class B(A):
          pass
    
      class C(A):
          attr = 3
    
      class D(B, C):
          pass
    
      if __name__ == '__main__':
          d = D()
          print 'attr = ', d.attr     # attr = 1複製代碼

    PS: 經過以上代碼的輸出結果能夠看出,新式類會廣度搜索,也就是一層層的向上搜索;經典類是深度優先,即遇到一個超類點就向上搜索。

裝飾器

Python的裝飾器被稱爲Python的語法糖,哪裏須要粘哪裏。

代碼示例:

@makeh1
@makeeitalic
def say():
    return 'Peter'

咱們但願輸出結果爲:<h1><i>Peter</i></h1>複製代碼

去看看官方文檔,答案就看下面:

def makeh1(func):
    def wrp():
        return "<h1>" + func() + "</h1>"
    return wrp

def makeeitalic(func):
    def wrp():
        return "<i>" + func() + "</i>"
    return wrp

@makeh1
@makeeitalic
def say():
    return 'Hello Peter'

print say()
輸出:<h1><i>Hello Peter</i></h1>複製代碼

實際應用場景:

使用過django的小夥伴想必都用過login_required裝飾器,可是若是用戶沒登陸的話login_required會重定向到登陸頁面;在作web開發的過程當中,咱們會常常用
ajax異步提交數據到後臺,這時若是再繼續使用原有的login_required裝飾器確定是不行了(該裝飾器不會重定向到登陸頁面,ajax也沒有任何返回結果),下面咱們改變下原有代碼:

from django.shortcuts import HttpResponse
import json

def is_authenticat(func):
    def wrp(req, **kwargs):
        if req.user.is_authenticated():
            return func(req, **kwargs)
        else:
            json_str = {'status': 0, 'msg': u'請登陸'}
            return HttpResponse(json.dumps(json_str), content_type='application/json')
    return wrp複製代碼

上述代碼便很好的解決了問題,也算是對Python裝飾器的一個很好的使用場景。

寫在結語

Python的奧妙遠不止於此

Python的深度還須要繼續探索

以上就是平時工做中所總結出來的經常使用的知識點

但願對你們之後的工做會有所幫助

相關文章
相關標籤/搜索