Python與其他語言(比如 java或者 C ++ )相比有較大的區別,其中最大的特點就是非常簡潔,如果按照其他語言的思路老師寫Python代碼,則會使得代碼繁瑣復雜,並且容易出現bug,在Python中,有個詞很火,Pythonic。有的同學可能不明白這個詞的意義,小編的理解就是有Python的寫法寫代碼,而非是其他語言的通用寫法,寫出python的特點,寫出Ppython的風格。
下面,就通過幾個示例來看看一下不同思維的Python代碼的差異。
1、變量值的交換
這個詞最常見,大家從最開始寫java及C++等語言代碼都會遇到這個問題,通過一個臨時變量來實現的“:
tmp = a a = b b = tmp
而Python中可以之間交換兩個變量,即:
a, b = b, a
2、列表推導式
列表推導式是java及C++等語言沒有的特性,能夠很簡潔的實現for循環,可以應用列表,集合或者子字典。
例如我們要求20以內的整除3的數的平方的列表,可以用如下代碼實現:
numbers = [] for x in xrange(20): if x % 3 == 0: numbers.append(x*x)
而通過列表推導式一行代碼就可以實現:
numbers = [x*x for x in xrange(20) if x % 3 == 0]
列表推導式可以用於集合和字典,將[...] 變為[...]。集合和字典的實現如下所示:
集合:
numbers = {x*x for x in range(0, 20) if x % 3 == 0}
字典:
numbers = {x: x*x for x in range(0, 20) if x % 3 == 0}
3、字符串拼接
這是一個老生常談的問題,當我們需要將數個字符串拼接起來的時候,習慣性的使用 “+” 作為連接字符串的手段。
然而,由於像字符串這種不可變對象在內存中生成后無法修改,合並后的字符串會重新開辟一塊內存空間來存儲。因此沒合並一次就會單獨開辟一塊內存空間,這樣會占用大量的內存,嚴重影響代碼的效率.
words =['I', ' ', 'LOVE', ' ', 'pYTHON', '.'] sentence = '' for word in words: sentence += '' + word
解決這個問題的辦法是使用字符串連接的join,Python寫法如下:
words = ['i', ' ', 'love', 'python',''] sentence = ''.join(words)
4.如何快速翻轉字符串
java 或者 C++ 等語言的寫法是新建一個字符串,從最后開始訪問員字符串:
a = 'I love python.' reverse_a = '' for i in range(0, len(a)): reverse_a += a[len(a) - i - 1]
而Python則將字符串看做list,而列表可以通過切片操作來實現翻轉:
a = "I LOVE PYTHON" reverse_a = a[::-1]
5、for/else 語句
在C語言或java語言中,我們尋找一個字符串是否在一個list中,通常會設置一個布爾型變量表示是否找到:
cities = ['Beijing', 'Shanghai', 'Tianjin', 'Shenzhen','Wuhan'] tofind = 'Shanghai' found = False for city in cities: if tofind == city: print('Found') found = True break if not found: print('Not found!')
而python中通過for ... else ... 會使得代碼很簡潔,注意else中的代碼快僅僅是在for循環中沒有執行break語句的時候執行:
cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan'] tofind = 'Shanghai' for city in citiees: if tofind == city: print('Found') break else: print('Not found!')
另外,while和try關鍵字都可以和else搭配使用
6、迭代對象善用enumerate類
enumerate類接收兩個參數,其中一個是可以地迭代的對象,另外一個是開始的索引。比如,我們想要的打印一份列表的索引機器內容,可以用如下代碼實現:
cities = ['Beijing', 'Shanghai', 'Wuhan'] index = 0 for city in cities: index = index + 1 print(index, ':', 'city')
而通過使用enumerate則極大的簡化了代碼,這里索引設置為從1開始(默認是從 0 開始):
cities = ['Beijing', 'Shanghai', 'Wuhan'] for index, ciity in enumerate(cities, 1): print(index, ':', city)
7、通過lambda來定義函數
lambda可以返回一個可以調用的函數對象,會使得代碼更為簡潔,若不使用lambda則需要單獨定義一個函數:
def f(x): return x*x map(f, [1,2,3,4,5,6,7,8])
使用lambda后僅僅使用一行代碼:
map(lambda x: x * x,[1,2,3,4,5,6,7,8] )
這里注意,lambda生成的是一個可以向其他函數一樣使用的函數對象,即
def f(x); return x *x 等價於 lambda x : x*x
8、應用上下文管理
在打開文件時,通常是通過捕獲異常來進行實現的,並且在finally模塊中對文件來進行關閉:
try: file = open('python.txt') for line in file: print(line) except: print('File error!') finally: file.close()
而通過上下文管理中的with語句可以讓代碼非常簡潔:
with open('python.txt') as file: for line in file: print(line)
9、使用裝飾器
裝飾器在Python中的應用非常廣泛,其特點是可以再具體函數執行之前或者之后做相關的操作。比如:執行前打印執行函數的相關信息,對函數的參數進行校驗,執行后記錄函數調用的相關日志等,使用裝飾器可以用如下代碼實現:
from time import ctime def foo(): print("[%s] %() is called" % (ctime(), foo.__name__)) print('Hello , Python')
這樣寫的問題是業務邏輯中會夾雜參數檢查,日志記錄等信息,是得代碼邏輯不夠清晰,所以,這種場合需要使用裝飾器:
from time import ctime def deco(func): def decorator(*args,**kwargs): print("[%s] %s() is called" % (citme(), func,__name__) return func(*args, **kwargs) return decorator @deco def foo(): print("Hello Python")
10、使用生成器
生成器與列表最大的區別就是,列表是一次行生成的,需要較大的內存空間;而生成器是需要的時候生成的,基本不占用內存空間,生成器分為生成器表達式和生成器函數:
先看一下列表:
l = [x for x in range(10)]
改成生成器只需要將[ .. ]變為(...),即
g = (x for x in range(10))
至於生成器函數,是通過yield關鍵字來實現的,我們一計算斐斐波那契數列為例,使用列表可以用如下代碼來說實現:
def fib(max): n, a, b = 0, 0, 1 fibonacci = [] while n < max: fibonacci,append(b) a, b = b, a + b n = n + 1 return fibonacci
而使用生成器則變為:
def fib(max); n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a+b n = n + 1
11、counter的使用
通常的詞頻統計中,我們的思路是:
需要一個字典,key值存儲單詞,value存儲對應的詞頻。當遇到一個單詞,判斷是否在這個字典中,如果是,則詞頻加1,如果否,則字典中新增這個單詞,同時對應的詞頻設置為1.
對應的Python代碼實現如下:
# 統計單詞出現的次數 def computeFrequencies(wordList): # 詞頻字典 wordfrequencies = {} for word in wordList: if word not in wordfrequescies; #單詞不在單詞詞頻字典中,詞頻設置為1 wordfrequescies[word] = 1 else: # 單詞在單詞詞頻字典中,詞頻加 1 wordfrequencies[word] += 1 return wordfrequencies
有沒有更簡單的方法嗎?答案是肯定的,就是使用Counter。collection中的Counter類就完成了這樣的功能,他是字典類的一個子類。Python代碼變得無比簡潔:
# 統計單詞出現的頻次 def computeFrequencies(wordList): # 詞頻字典 wordfrequencies = Counter(wordList) return wordfrequencies
12、鏈式比較
在實際的數字比較中,我們可能需要多次比較多次,比如我們判斷學習成績是否位與某個區間:
x = 79 >>> x < 80 and x > 70 True
變更Pythonic的寫法變身鏈式比較:即:
x = 79 >>> 80 < x 90 False >>> 70 < x < 80 True
這種寫法給人的感受也更為直觀易懂。
13、函數返回多個值
在java語言中,當函數需要返回多個值時,通常的做法是生成一個Response對象,然后將要返回的值寫入對象內部,而Python不需要這樣做。可以直接返回多個值:
def f(); error_code = 0 error_desc = "成功" return error_code, error_desc
使用的時候也會非常簡單:
code, desc = f()
print(code, desc)
14、使用*運算符
*運算符和 ** 運算符完美的解決了將元組參數、字典參數進行 unpack,從而簡化了函數定義的形式,如:
def fun(*args): for eacharg in args: print('tuple arg:', eacharg) fun('I', 'LOVE', 'PYTHON')
運行的結果:
tuple arg: I
tuple arg: love
tuple arg: Python
15、找出列表中出現最多的數:
這是經常遇到的一個問題。解決這個問題的其中一個思路是按照標題 11 提供的詞頻統計的方法,先統計詞頻,然后遍歷字典,找出具有最大詞頻的數字,有沒有簡潔的方式?
當然,Python代碼入下:
num = [1,2,3,4,4,4,4, 2,3,4,5,6,7,8,9] ptint(max(set(num), key=num.count))