你是否是常常對調用模塊時輸入一長串模塊索引感到頭疼?說實在的,數量少的時候或許還能夠勉強忍受,一旦程序規模上去了,這也是一項不容小覷的工程html
#Bad
import urllib.request
url = r'http://www.baidu.com'
req = urllib.request.Request(url)
response = urllib.request.urlopen(req)
#Good
from urllib import request
url = r'http://www.baidu.com'
req = request.Request(url)
response = request.urlopen(req)
若是遇到不一樣package中重複的模塊,咱們如何區分呢?,示例以下:python
from module_a import fun as a_fun from module_b import fun as b_fun
這樣的方式還適合模塊名比較長的方法,舉例以下:git
from bs4 import BeautifulSoup as BS html = ''' <html> ...... </html> ''' soup = BS(html)
這是一個很是有用的功能,惋惜不多人知道。github
當你在交互界面敲代碼,得到一個臨時結果,卻沒有用變量名去保存它的時候,能夠用"_"來獲取最近一次臨時結果。數組
>>> 3*5
15
>>> _
15
在"_"中存儲最後輸出的值。這在交互式模式中是很是有用的,當你在過程當中沒有保存計算結果,或者你想看最後一步執行的輸出結果。安全
直接用+ 號比用''.join方法更佔用內存資源閉包
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
# Bad
string = ['a','b','c','d','e','f','g','h','ss']
def fun(string):
all_string = ''
for i in string:
all_string += i
return all_string
# Good
string = ['a','b','c','d','e','f','g','h'.'ss']
def fun(string):
all_string = ''.join(string)
return all_string
它是Python的內建函數,zip函數接受任意多個(包括0個和1個)序列做爲參數,返回一個包含tuple的list。zip()函數能夠在不少場景簡化你的代碼。app
矩陣的行列互換ide
##bad
>>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> re_a = [[row[col] for row in a] for col in range(len(a))] >>> re_a [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
##good >>> re_a = list(zip(*a)) >>> re_a [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
交換dict的鍵值函數
##bad
>>> a = {'a':1, 'b':2, 'c':3, 'd':4}
>>> def reve_dict(a):
... new_dict = {}
... for k,v in a.items():
... new_dict[v] = k
... return new_dict
...
>>> reve_dict(a)
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
##good
>>> def reve_dict2(a):
... k = a.keys()
... v = a.values()
... new_dict = dict(zip(v,k))
... return new_dict
...
>>> reve_dict2(a)
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
合併list相鄰項
>>> a = [1, 2, 3, 4, 5, 6]
>>> a[::2]
[1, 3, 5]
>>> a[1::2]
[2, 4, 6]
>>> list(zip(a[::2],a[1::2]))
[(1, 2), (3, 4), (5, 6)]
>>> a = list(zip(a[::2],a[1::2]))
>>> a
[(1, 2), (3, 4), (5, 6)]
# Bad tmp = a a = b b = tmp #Good a, b = b, a
>>> a = [8,12,45,33,8] >>> for index, value in enumerate(a): ... print(index,value) ... 0 8 1 12 2 45 3 33 4 8
try: pass except (ExceptionA,ExceptionB,.....) as e: pass
8.把列表分割成一樣大小的塊
>>> a
[8, 12, 45, 33, 8]
>>> list(zip( *[iter(a)]*2))
[(8, 12), (45, 33)]
a = ['a', 'b', 'c', 'd', 'e', 'f'] a_i = a.index(a) >>> 0
10.如何快速反轉字符串?
##bad
>>> a = 'python reverse method'
>>> list_a = list(a)
>>> list_a.reverse()
>>> re_a = ''.join(list_a)
>>> re_a
'dohtem esrever nohtyp'
##good
>>> a = 'python reverse method'
>>> re_a = a[::-1]
>>> re_a
'dohtem esrever nohtyp'
11. 用with打開文件
平時在使用相似文件的流對象時,使用完畢後要調用close方法關閉。with…as語句提供了一個很是方便的替代方法:open打開文件後將返回的文件流對象賦值給f,而後在with語句塊中使用。with語句塊完畢以後,會隱藏地自動關閉文件。
with open('foo.txt','r') as f:
f.read()
with語句須要支持上下文管理協議的對象
, 上下文管理協議包含 __enter__ 和 __exit__ 兩個方法. with語句創建運行時上下文須要經過這兩個方法執行進入和退出
操做.
其中上下文表達式
是跟在with以後的表達式, 該表達示返回一個上下文管理對象
知道具體原理, 咱們能夠自定義支持上下文管理協議的類, 類中實現 __enter__ 和 __exit__ 方法
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
class MyWith(object):
def __init__(self):
print("__init__ method")
def __enter__(self):
print("__enter__ method")
return self # 返回對象給as後的變量
def __exit__(self, exc_type, exc_value, exc_traceback):
print("__exit__ method")
if exc_traceback is None:
print("Exited without Exception")
return True
else:
print("Exited with Exception")
return False
def test_with():
with MyWith() as my_with:
print("running my_with")
print("------分割線-----")
with MyWith() as my_with:
print("running before Exception")
raise Exception
print("running after Exception")
if __name__ == '__main__':
test_with()
執行結果以下:
__init__ method __enter__ method running my_with __exit__ method Exited without Exception ------分割線----- __init__ method __enter__ method running before Exception __exit__ method Traceback (most recent call last): Exited with Exception File "/Users/JasonWang/PycharmProject/spider/mywith.py", line 28, in <module> test_with() File "/Users/JasonWang/PycharmProject/spider/mywith.py", line 25, in test_with raise Exception Exception
證實了會先執行 __enter__ 方法, 而後調用with內的邏輯, 最後執行 __exit__ 作退出處理, 而且, 即便出現異常也能正常退出
crash = dict(zip(range(10 **0xA), range(10 **0xA))) ##說明 range(10 **0xA) >>> range(0, 10000000000) 用range()生成,不會拋MemoryError,而後進行壓縮,再轉換成dict,內存很快會消耗乾淨的,電腦就一動不動了......
13.顯示有限的接口到外部
當發佈python第三方package時, 並不但願代碼中全部的函數或者class能夠被外部import, 在__init__.py
中添加__all__
屬性,
該list中填寫能夠import的類或者函數名, 能夠起到限制的import的做用, 防止外部import其餘函數或者類
#!/usr/bin/env python # -*- coding: utf-8 -*- from base import APIBase from client import Client from decorator import interface, export, stream from server import Server from storage import Storage from util import (LogFormatter, disable_logging_to_stderr, enable_logging_to_kids, info) __all__ = ['APIBase', 'Client', 'LogFormatter', 'Server', 'Storage', 'disable_logging_to_stderr', 'enable_logging_to_kids', 'export', 'info', 'interface', 'stream']
相對filter
而言, map和reduce使用的會更頻繁一些, filter
正如其名字, 按照某種規則過濾
掉一些元素
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
lst = [1,2,3,4,5]
# 全部奇數都會返回True, 偶數會返回False被過濾掉
f_list =filter(lambda x:x % 2 !=0,lst)
print(list(f_list))
當條件知足時, 返回的爲等號後面的變量, 不然返回else後語句
>>> lst = [4,5,6] >>> new_l =lst[1] if lst is not None else None >>> new_l 5
def singleton(cls):
instances = dict()
def _singleton(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return _singleton
@singleton
class Test(object):
pass
if __name__ == '__main__':
tt1 = Test()
tt2 = Test()
print(tt1,tt2)
類中兩種經常使用的裝飾, 首先區分一下他們
對象
classmethod裝飾器
, 類方法(給人感受很是相似於OC中的類方法), 其中第一個隱式參數爲類
staticmethod裝飾器
, 沒有任何隱式參數. python中的靜態方法相似與C++中的靜態方法
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: Jason Wang class A(object): # 普通成員函數 def foo(self, x): print("executing foo(%s, %s)" % (self, x)) @classmethod # 使用classmethod進行裝飾 def class_foo(cls, x): print("executing class_foo(%s, %s)" % (cls, x)) @staticmethod # 使用staticmethod進行裝飾 def static_foo(x): print("executing static_foo(%s)" % x) def test_three_method(): obj = A() # 直接調用噗通的成員方法 obj.foo("para") # 此處obj對象做爲成員函數的隱式參數, 就是self obj.class_foo("para") # 此處類做爲隱式參數被傳入, 就是cls A.class_foo("para") #更直接的類方法調用 obj.static_foo("para") # 靜態方法並無任何隱式參數, 可是要經過對象或者類進行調用 A.static_foo("para") if __name__ == '__main__': test_three_method() # 函數輸出 # executing foo(<__main__.A object at 0x1029ef278>, para) # executing class_foo(<class '__main__.A'>, para) # executing class_foo(<class '__main__.A'>, para) # executing static_foo(para) # executing static_foo(para)
將property
與裝飾器結合實現屬性私有化(更簡單安全的實現get和set方法
)
#python內建函數 property(fget=None, fset=None, fdel=None, doc=None)
fget
是獲取屬性的值的函數,fset
是設置屬性值的函數,fdel
是刪除屬性的函數,doc
是一個字符串(like a comment).從實現來看,這些參數都是可選的
property有三個方法getter()
, setter()
和delete()
來指定fget, fset和fdel。 這表示如下這行
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: Jason Wang class Student(object): @property #至關於property.getter(score) 或者property(score) def score(self): return self._score @score.setter #至關於score = property.setter(score) def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value
__iter__
的結合, 咱們能夠把一個對象變成可迭代的__str__
的重寫, 能夠直接經過想要的形式打印對象class MyIter():
def __init__(self):
self.lst = [1, 2, 3, 4, 5]
def read(self):
for ele in range(len(self.lst)):
yield ele
def __iter__(self):
return self.read()
def __str__(self):
return ','.join(map(str, self.lst))
__repr__ = __str__
def t_iter():
obj = MyIter()
for num in obj:
print(num)
print(obj)
if __name__ == '__main__':
t_iter()
##result
0
1
2
3
4
1,2,3,4,5
partial使用上很像C++中仿函數(函數對象).
在stackoverflow給出了相似與partial的運行方式
def partial(func, *part_args):
def wrapper(*extra_args):
args = list(part_args)
args.extend(extra_args)
return func(*args)
return wrapper
利用用閉包的特性綁定預先綁定一些函數參數, 返回一個可調用的變量, 直到真正的調用執行
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
def partial(func, *part_args):
def wrapper(*extra_args):
args = list(part_args)
args.extend(extra_args)
return func(*args)
return wrapper
from functools import partial
def sum(a, b):
return a + b
def test_partial():
fun = partial(sum, 2) # 事先綁定一個參數, fun成爲一個只須要一個參數的可調用變量
print(fun(3)) # 實現執行的便是sum(2, 3)
if __name__ == '__main__':
test_partial()
##執行結果:
5
eval我理解爲一種內嵌的python解釋器(這種解釋可能會有誤差), 會解釋字符串爲對應的代碼並執行, 而且將執行結果返回
看一下下面這個例子
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: Jason Wang def test_first(): return 3 def test_second(num): return num action = { # 能夠看作是一個sandbox "para": 6, "test_first" : test_first, "test_second": test_second, } def test_eavl(): condition = "para == 6 and test_second(test_first()) < 5" res = eval(condition, action) # 解釋condition並根據action對應的動做執行 print(res) if __name__ == '__main__': test_eavl()
##result
True
exec
和eval
在執行代碼時, 除了返回值其餘行爲都相同compile(source, '<string>', mode)
編譯字節碼. mode的取值爲exec
和eval
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
def test_first():
print("hello")
def test_second():
test_first()
print("second")
def test_third():
print("third")
action = {
"test_second": test_second,
"test_third": test_third
}
def test_exec():
exec("test_second()") in action
if __name__ == '__main__':
test_exec() # 沒法看到執行結果
##
hello
second
getattr(object, name[, default])
Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, ‘foobar’) is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.
經過string類型的name, 返回對象的name屬性(方法)對應的值, 若是屬性不存在, 則返回默認值, 至關於object.name
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
# 使用範例
class MyGetAttr(object):
test = "test attribute"
def say(self):
print("test method")
def my_getattr():
my_test = MyGetAttr()
try:
print(getattr(my_test, "test"))
except AttributeError:
print("Attribute Error!")
try:
getattr(my_test, "say")()
except AttributeError: # 沒有該屬性, 且沒有指定返回值的狀況下
print("Method Error!")
if __name__ == '__main__':
my_getattr()
##
test attribute
test method
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
import sys
import optparse
def process_command_line(argv):
"""
Return a 2-tuple: (settings object, args list).
`argv` is a list of arguments, or `None` for ``sys.argv[1:]``.
"""
if argv is None:
argv = sys.argv[1:]
print(argv)
# initialize the parser object:
parser = optparse.OptionParser(
formatter=optparse.TitledHelpFormatter(width=78),
add_help_option=None)
# define options here:
parser.add_option( # customized description; put --help last
'-h', '--help', action='help',
help='Show this help message and exit.')
settings, args = parser.parse_args(argv)
# check number of arguments, verify values, etc.:
if args:
parser.error('program takes no command-line arguments; '
'"%s" ignored.' % (args,))
# further process settings & args if necessary
return settings, args
def main(argv=None):
settings, args = process_command_line(argv)
print('settings:',settings,'arg:',args)
# application code here, like:
# run(settings, args)
return 0 # success
if __name__ == '__main__':
status = main()
print(status)
sys.exit(status)
# 從csv中讀取文件, 基本和傳統文件讀取相似
import csv
with open('data.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
print row
# 向csv文件寫入
import csv
with open( 'data.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerow(['name', 'address', 'age']) # 單行寫入
data = [
( 'xiaoming ','china','10'),
( 'Lily', 'USA', '12')]
writer.writerows(data) # 多行寫入
只發一張網上的圖, 而後差文檔就行了, 這個是記不住的
一個很是好用, 不少人又不知道的功能
>>> name = 'Jason'
>>> 'my name is {name}'.format(name=name)
'my name is Jason'