Python2即將淘汰,分享python3 才能用的特性(13個)

特性 1: 高級解包

使用解包交換變量很是方便,在 python3 中,這個特性獲得了增強,如今你能夠這樣作:python

a, b, *rest = range(10) print('a:', a) print('b:', b) print('rest:', rest) ##> a: 0 ##> b: 1 ##> rest: [2, 3, 4, 5, 6, 7, 8, 9] 

rest 能夠在任何位置,好比這樣:編程

a, *rest, b = range(10) print('rest', rest) ##> rest [1, 2, 3, 4, 5, 6, 7, 8] *rest, b = range(10) print('rest', rest) ##> rest [0, 1, 2, 3, 4, 5, 6, 7, 8] 

使用 python 得到文件的第一行和最後一行內容。api

with open('use_python_to_profit.txt') as f: first, *_, last = f.readlines() # 注意,這會讀取全部內容到內存中 print('first:', first) print('last:', last) ##> first: step 1: use python ##> last: step 10: profit 

 

特性 2: 強制關鍵詞參數數組

def f(a, b, *args, option=True): pass 

若是你用以上寫法來寫一個函數,那麼你限定了調用參數時,必需要這樣寫 f(a, b, option=True)app

若是你不想收集其餘參數,你能夠用 * 代替 *args,好比這樣:async

def f(a, b, *, option=True): pass 

當你碰上這種事情:哎呀,我不當心傳遞太多參數給函數,其中之一會被關鍵字參數接收,而後程序原地爆炸了。函數

def sum(a, b, biteme=False): if biteme: print('一鍵刪庫') else: return a + b sum(1, 2) ##> 3 sum(1, 2, 3) ##> 一鍵刪庫. 

 

因此,之後千萬別這樣寫,爲了你的下半生可以過上平靜的日子,你應該這樣:fetch

def sum(a, b, *, biteme=False): if biteme: print('一鍵刪庫') else: return a + b 

試一下不合法的調用:this

sum(1, 2, 3) ##> TypeError: sum() takes 2 positional arguments but 3 were given 

有時你會想寫這樣一個方法編碼

def maxall(iterable, key=None): """ 返回一個列表中的最大值 """ key = key or (lambda x: x) m = max(iterable, key=key) return [i for i in iterable if key(i) == key(m)] maxall(['a', 'ab', 'bc'], len) ##> ['ab', 'bc'] 

咱們應該用max(iterable, *, key=None)來寫這個函數。你在寫代碼時,也能夠用關鍵詞參數使你的 api 具備更好的擴展性。

def extendto(value, *, shorter=None, longer=None): """ Extend list `shorter` to the length of list `longer` with `value` """ if shorter is None or longer is None: raise TypeError('`shorter` and `longer` must be specified') if len(shorter) > len(longer): raise ValueError('The `shorter` list is longer than the `longer` list') shorter.extend([value]*(len(longer) - len(shorter))) 

咱們能夠用 extendto(10, shorter=a, longer=b) 的方式調用這個方法,之後咱們要修改這個接口的傳參方式時,也不用修改已有代碼啦。

 

特性 3:鏈式異常

如今你在寫一個函數,因爲可能會出現錯誤,你打算 catch 可能出現的異常,作一些額外的工做,而後再拋出另外一種異常。

import shutil def mycopy(source, dest): try: shutil.copy2(source, dest) except OSError: # We don't have permissions. More on this later raise NotImplementedError("automatic sudo injection") 

python3 中會依次把異常記錄下來

mycopy(1, 2)

---------------------------------------------------------------------------
SameFileError                             Traceback (most recent call last)
<ipython-input-26-7970d14296a0> in mycopy(source, dest)
      4     try:
----> 5         shutil.copy2(source, dest)
      6     except OSError: # We don't have permissions. More on this later

/usr/lib/python3.5/shutil.py in copy2(src, dst, follow_symlinks)
    250         dst = os.path.join(dst, os.path.basename(src))
--> 251     copyfile(src, dst, follow_symlinks=follow_symlinks)
    252     copystat(src, dst, follow_symlinks=follow_symlinks)

/usr/lib/python3.5/shutil.py in copyfile(src, dst, follow_symlinks)
     97     if _samefile(src, dst):
---> 98         raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
     99 

SameFileError: 1 and 2 are the same file

During handling of the above exception, another exception occurred:

NotImplementedError                       Traceback (most recent call last)
<ipython-input-27-ddb6bcd98254> in <module>()
      1 # python3 中會依次把異常記錄下來
----> 2 mycopy(1, 2)

<ipython-input-26-7970d14296a0> in mycopy(source, dest)
      5         shutil.copy2(source, dest)
      6     except OSError: # We don't have permissions. More on this later
----> 7         raise NotImplementedError("automatic sudo injection")

NotImplementedError: automatic sudo injection

 

特性 4: 更好用的 OSError 子類

剛剛給你的代碼其實不正確,OSError 實際上包含了不少類異常,好比權限不夠,文件沒找到,不是一個目錄等,而咱們默認是權限不夠。

python3 添加了大量的新 Exception 類型,因此你能夠這樣作:

def mycopy(source, dest): try: shutil.copy2(source, dest) except PermissionError: raise NotImplementedError("automatic sudo injection") 

 

特性 5: 一切皆迭代器

def naivesum(N): A = 0 for i in range(N + 1): A += i return A naivesum(100000000) # 內存爆炸 

 

在 python3 中,range,zip,dict.values 以及其它,都是返回迭代器,因此這對內存很友好。

若是你但願獲得一個列表,要作的僅僅是在外層加一個 list,顯示的聲明永遠比隱式地更好,你很難再寫出一個吃內存的代碼了。

 

特性 6: 不是一切都能比較

 

在 python3 中,這個很是 buggy 的特性被取消啦:

'one' > 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-33-55b5025c2335> in <module>()
----> 1 'one' > 2

TypeError: unorderable types: str() > int()

 

特性 7: yield from

若是你用 generator 的話,這個是一個很是好的特性。在之前,你是這麼寫代碼的:

for i in gen(): yield i 

如今是這樣

yield from gen() 

沒有看懂?來一個例子,好比這樣,咱們但願獲得 [0, 0, 1, 1, 2, 2, ...] 的列表用於迭代,咱們有如下寫法:

# 不錯的方法,使用 yield def dup(n): for i in range(n): yield i yield i # 更好的方法,使用 yield from def dup(n): for i in range(n): yield from [i, i] 

咱們知道,迭代器的方式很是好,首先在內存上它頗有優點,而且能夠按需計算,每次只計算要用的值。若是你須要一個列表的時候,只須要在外層加一個 list,若是你須要切片 slicing,能夠用 itertools.islice()

 

特性 8: asyncio

如今你能夠用更方便的協程調用了

async def fetch(host, port): r, w = await open_connection(host, port) w,write(b'GET /HTTP/1.0\r\n\r\n') while (await r.readline()).decode('latin-1').strip(): pass body = await r.read() return body async def start(): data = await fetch('Welcome to Python.org', 80) print(data.deode('utf-8')) 

 

特性 9: 新的標準庫

ipaddress 庫

import ipaddress print(ipaddress.ip_address('192.168.0.1')) print(ipaddress.ip_address('2001:db8::')) ##> 192.168.0.1 ##> 2001:db8:: 

functools.lrc_cache 裝飾器

from functools import lru_cache from urllib.error import HTTPError import urllib.request @lru_cache(maxsize=32) def get_pep(num): 'Retrieve text of a Python Enhancement Proposal' resource = 'http://www.python.org/dev/peps/pep-%04d/' % num try: with urllib.request.urlopen(resource) as s: return s.read() except HTTPError: return 'Not Found' for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991: pep = get_pep(n) print(n, len(pep)) get_pep.cache_info() ##> CacheInfo(hits=3, misses=8, maxsize=32, currsize=8) 

enum 類

from enum import Enum class Color(Enum): red = 1 green = 2 blue = 3 

 

特性 10: Fun

據說你會中文編程?

簡歷 = "knows python" π = 3.1415926 

類型標註

def f(a: int, b: int = 2) -> int: return 10 print(f.__annotations__) ##> {'return': <class 'int'>, 'a': <class 'int'>, 'b': <class 'int'>} 

 

特性 11: Unicode 編碼

這是新手遇到的最多的問題,爲何個人命令行輸出是亂碼?

python2 中的 str 是字節數組

python3 中的 str 是 unicode 字符串,只有 unicode 才能表示中文。

 

特性 12: 矩陣相乘

python3 中 @ 能夠被重載了,因此用 numpy 中的矩陣乘法時能夠這麼來(我在 tensorflow 中也常常這樣寫)

import numpy as np a = np.array([[1, 0], [0, 1]]) b = np.array([[4, 1], [2, 2]]) # 舊寫法 print(np.dot(a, b)) # 新寫法 print(a @ b) 

 

特性 13: pathlib

這是一個特別好用的面向對象路徑處理庫,更好的寫法

from pathlib import Path directory = Path("/etc") filepath = directory / "hosts" if filepath.exists(): print('hosts exist') 
相關文章
相關標籤/搜索