python技巧

bound2020發表於2018-04-25

以下是我從網上和書上找到的有用並且也是pythonic的技巧,其中大部分都已經用在自己程式碼裡了。大部分都是對於python 2.7,而對於python 3的以後也會另外整理一份。


  • 用位運算判斷奇偶性:

def is_even(x):

    return False if x & 1 else True


  • 迴圈時, 使用 while 1 while True 更快!

  • 檔案相關操作:

os.chdir(path)    改變當前工作目錄 

os.path.dirname(path) #返回檔案路徑

os.path.abspath(path) #返回絕對路徑

os.path.isdir(dir)    #判斷是否是個資料夾 

os.path.isfile(file)    #判斷是否是檔案 


  • 處理命令列輸入

option_parser = OptionParser() 

option_parser.add_option(“-d”, “—date”, dest=“date”, help=“input date”) 

option_parser.add_option(“-r”, “—rb”, dest=“rb_num”, help=“rb number”) 

(options, args) = option_parser.parse_args() 

print options.date, options.rb_num 


  • 讀取配置檔案:

parser = ConfigParser.ConfigParser() 

parser.read('./conf.ini') 

host, port, user, passwd = [x[1] for x in parser.items(dbname)] 


  • 子程式呼叫方法: 

proc = subprocess.Popen(find_cmd, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)    #後面兩個pipe不要忘加 

cout, cerf = proc.communicate()    #程式結束才會返回 

return_code = proc.poll()    #獲取程式返回碼 


  • sys.modules是一個全域性字典,該字典是Python啟動後就載入在記憶體中。每當程式設計師匯入新的模組,sys.modules都將記錄這些模組。字典sys.modules對於載入模組起到了緩衝的作用。當某個模組第一次匯入,字典sys.modules將自動記錄該模組。當第二次再匯入該模組時,python會直接到字典中查詢,從而加快了程式執行的速度。

  • log的使用:

import logging

logger = logging.getLogger(__name__)

logger.addHandler(handler)

logger.setLevel(logging.DEBUG)

#通過logging.basicConfig對日誌的輸出格式及方式做修改, 如:

logging.basicConfig(level=logging.DEBUG,

     format='',

     datefmt='%a, %d %b %Y %H:%M:%S',

     filename='mylog.log'

)

console = logging.StreamHandler()

#設定日誌級別

console.setLevel(logging.info)

formatter = logging.Formatter()

comsole.setFormatter(formatter)

logging.getLogger().addHandler(console)

logging.debug('This is a debug message')

logging.info('this is a info message')


  • urllib2的使用:

import urllib2

url = '' 

user_agent = 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/48.0.2564.23 Mobile Safari/537.36' 

req = urllib2.Request(url)     

req.add_header('User-Agent', user_agent)    #新增報頭 

response = urllib2.urlopen(req) 

page = response.read() 

print response.geturl()    #如果有重定向,獲得最終url 


  • 使用代理編寫爬蟲:

1. 引數是一個字典{'型別':'代理ip:埠'}

proxy_support = urllib2.ProxyHandler({})

2. opener = urllib2.build_opener(proxy_support)

3. opener.open(url)

網頁狀態碼,301永久重定向,302臨時重定向,404網頁不存在,403網頁禁止訪問

import cookielib

cookie = cookielib.CookieJar()

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))

response = opener.open(url)

某些站點有所謂的反盜鏈設定,其實就是檢查你傳送請求的header裡面,referer站點是不是他自己, 所以我們只需要像把headersreferer改成該網站即可


  • with的魔力

with語句需要支援上下文管理協議的物件, 上下文管理協議包含__enter____exit__兩個方法. with語句建立執行時上下文需要通過這兩個方法執行進入和退出操作.

property與裝飾器結合實現屬性私有化(更簡單安全的實現getset方法)

class Student(object):    #object as the parent class 

    def __init__(self): 

        self._score = 0 

     

    @property 

    def score(self):    #getter 

        return self._score 



    @score.setter 

    def score(self, value):    #setter 

        #some check 

        self._score = value 


  • 神奇partial

from functools import partial 

def sum(a, b): 

    return a + b 


def test(): 

    func = partial(sum, 2)    #sum的第一個引數繫結為2 

    print func(3)    #sum的第二個引數為3 


  • pythonunicode和中文轉換,這個很容易搞錯

python2: str->byte: encode 

               byte->str: decode 

python2中的str其實是byte,所以要用decode方法列印出真正的內容 

在程式碼檔案的開頭要定義encode的方式:# -*- coding: utf-8 -*- 


  • import技巧:

__import__動態載入模組,比如事先不知道模組的名字,或者載入配置檔案中字元形式的模組 

__import__ (name[, globals[, locals[, fromlist[, level]]]])

name (required): 被載入 module 的名稱

globals (optional): 包含全域性變數的字典,該選項很少使用,採用預設值 global()

locals (optional): 包含區域性變數的字典,內部標準實現未用到該變數,採用預設值 local()

fromlist (Optional): 被匯入的 submodule 名稱

level (Optional): 匯入路徑選項,預設為 -1,表示同時支援 absolute import relative import


  • 計算向量的餘弦相似度: 

Module1 = np.linalg.norm(a) 

Module2 = np.linalg.norm(b) 

inner_prod = np.dot(a, b) 

Cos_sim = inner_prod / (module1 * module2) 


  • 使用預設字典

# 好處是放入新的key時不用判斷是否已存在,直接用d[key].append(val)即可

d = collections.defaultdict(lambda:[])


  • namedtuple

cards = collections.namedtuple('cards', ['color', 'suit'])


  • zip的妙用

# 每三個生成一個tuple

l = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8]

zip(*[iter(l)] *3)


  • pow(x, y, z)  #(x^y) mod z

  • 使用itertools.chain()將二維列表打散成一維的

>>> from itertools import *

>>> l = [[1, 2], [3, 4]]

>>> list(chain(*l))

[1, 2, 3, 4]


  • Finding the most frequent element in a list, x:

max(set(x), key=x.count)


  • 一句話生成n-gram

ngrams = zip(*[words[i:] for i in range(n)])


  • A fast way to compute large fibonacci numbers using generators:

     def fibonacci_generator():

1. a,b = 0,1

2. while True:

3.     yield a

4.     a,b = b, a+b

f = fibonacci_generator()

fib_nums = [f.next() for i in xrange(300)


from operator import itemgetter

metro_data = [

... ('Tokyo' , 'JP', 36.933, ( 35.689722 , 139.691667 )),

... ('Delhi NCR' , 'IN', 21.935, ( 28.613889 , 77.208889 )),

... ('Mexico City' , 'MX', 20.142, ( 19.433333 , - 99.133333 )),

... ('New York-Newark' , 'US', 20.104, ( 40.808611 , - 74.020386 )),

... ('Sao Paulo' , 'BR', 19.649, ( -23.547778, -46.635833)),

... ]

# 對字典排序,當然也可以用lambda

sorted(metro_data, key=itemgetter(0)) #按照第一個欄位進行排序,即城市名


例如:按照字典的value進行排序

sorted(dict.items(), key=itemgetter(1), reverse=True)


cc_name = itemgetter(1, 0)

for city in metro_data:

     print cc_name(city)


  • 階乘計算方法:

def fact(n):

     return reduce(lambda a,b: a*b, range(1, n+1))


y = np.empty((10, 1))

y.fill(value)         #申請一個10*1的向量,值填充為value


  • python 獲取當前時間 time.strftime( ISOTIMEFORMAT, time.localtime() )
  • 計算時間差,其中入參為seconds

date1 = time.strptime(time.ctime(float(c[3])))

date1 = datetime.datetime(date1[0],date1[1],date1[2],date1[3],date1[4],date1[5])

date2 = time.strptime(time.ctime(float(a[6])))

date2 = datetime.datetime(date2[0],date2[1],date2[2],date2[3],date2[4],date2[5])

print (date2-date1).seconds


  • 檢查一個資料夾是否存在,如果不存在就建立它:

if not os.path.exists(directory):

     os.makedirs(directory)


  • from subprocess import check_output   # 父程式等待子程式完成
  • np.array_equal(a, b) #判斷兩個陣列大小和元素是否相等

import seaborn as sns     #seaborn也是資料視覺化工具包,接受dataframe格式的資料

tips = sns.load_dataset("tip")

g = sns.FacetGrid(tips, col="time")

The main approach for visualizing data on this grid is with the FacetGrid.map() method. Provide it with a plotting function and the name(s) of variable(s) in the dataframe to plot

g.map(plt.hist, "tip")

  • docopt根據你寫的文件描述,可以自動為你生成解析器,可以非常容易的為你的python程式建立命令列介面(Command Line InterfaceCLI)。
  • the operator == compares the values of objects, while is compares their identities

The presence of references is what keeps an object alive in memory. When the reference count of an object reaches zero, the garbage collector disposes of it.

repr()

Return a string representing the object as the developer wants to see it.

str()

Return a string representing the object as the user wants to see it.


  • 可利用python進行傳輸

python -m SimpleHTTPServer 80


  • 將秒數轉化成可讀的時間格式

datetime.datetime.fromtimestamp(1458369661).strftime("%Y-%m-%d”)


  • 合併list:

a = [[1, 2], [3, 4], [5, 6], [7, 8]]

b = sum(a, [])

# b = [1, 2, 3, 4, 5, 6, 7, 8]


  • if判斷時儘量避免直接和TrueFalse比較, 如:

if int_value:    #判斷是否為0

    print int_vaue

但,當需要和None比較時,使用is判斷

if input is None:

    print “Empty value”


  • 避免在if語句中重複寫變數

if name == ‘Tom’ or name == ‘Peter’ => if name in (‘Tom’, ‘Peter’)


  • enumerate可以生成下標:

for index, element in enumerate(list):

    print index, element


  • for…else…中的else用於for迴圈中沒有一個元素滿足條件的操作,如:

for user in get_all_users():

    for email_address in user.get_email_address():

        if is_malformed(email_address):

            print “has a malformed mail”

            break

    else:

        print “All mails are valid”


  • 函式的預設引數不要用[],最好使用None

def func(mylist=[]) => def func(mylist=None)


  • python3中可以使用*捕獲list剩餘的元素: first, second, third, * = my_list[0:10]
  • 最好為字典的get操作提供一個預設值,如:

lov_severity = config.get(’severity’, ’Info’)


  • 字典推導式:

user_email = {user: get_mail(user) for user in phonebook if has_mail(user)}

result_list = ['True', 'False', 'File not found']

result_string = ''.join(result_list)

  • 定義一個class時候,最好定義__str__()方法,列印關於這個classreadable資訊

  • 使用_代替不需要的變數,

(name, age, _, _) = get_user_info(user)


  • main函式最後加上sys.exit,如果有錯則返回錯誤程式碼,否則就返回0sys.exit(0)

  • 如果想要import多個包,可以放在圓括號中,如

from foo import (bar, bad, qux, quux)


  • 推薦的模組匯入順序:

1. 標準庫的模組

2. 安裝在sitepackages中的第三方庫

3. 當前專案中已有的模組


  • 叉乘的寫法:sum(map(operator.mul, vec1, vec2))

accumulate([1,2,3,4,5]) --> 1 3 6 10 15

chain('ABC', 'DEF') --> A B C D E F    #用於打散多維list

compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F    

dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1    #從第一個不滿足條件的元素開始,遍歷之後的所有元素

filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8    #過濾不滿足條件的元素

starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000

takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4    #選擇滿足條件的元素


相關文章