python3.6+ 新特性一

  1. Python 3.7 將引入 dataclass 裝飾器

     import dataclasses
    
     @dataclasses.dataclass
     class InventoryItem:
         '''Class for keeping track of an item in inventory.'''
         name: str
         unit_price: float
         quantity_on_hand: int = 0
     
         def total_cost(self) -> float:
             return self.unit_price * self.quantity_on_hand
     
     
     inv=InventoryItem('PYTHON','200',1)
     
     print(f"{inv.unit_price!r}")
    

    我們?nèi)サ袅?strong>init方法,以確保 data class 裝飾器可以添加它生成的對(duì)應(yīng)方法。不過,我們?cè)谶@個(gè)過程中失去了一些功能,我們的 Python 3.6 構(gòu)造函數(shù)不僅定義了所有的值,還試圖解析日期,我們?cè)鯓硬拍苡?data class 來做到這一點(diǎn)呢?

    如果要覆蓋 init,我們將失去 data class 的優(yōu)勢(shì),因此,如果要處理任何附加功能可以使用新的 dunder 方法:post_init,讓我們看看post_init方法對(duì)于我們的包裝類來說是什么樣子的:

     def __post_init__(self):
        if type(self.release_date) is str:
            self.release_date = dateutil.parser.parse(self.release_date)
     
        if type(self.created) is str:
            self.created = dateutil.parser.parse(self.created)
     
        if type(self.edited) is str:
            self.edited = dateutil.parser.parse(self.edited)
    

    更多好東西

    通過使用裝飾器的選項(xiàng),可以為用例進(jìn)一步定制 data class,默認(rèn)選項(xiàng)是:

    @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

init決定是否生成__init__ dunder 方法

repr決定是否生成__repr__ dunder方法

eq對(duì)__eq__ dunder 方法也是如此,它決定相等性檢查的行為(your_class_instance == another_instance)

order 實(shí)際上創(chuàng)建了四種 dunder 方法,它們確定所有檢查小于,and/or,大于的行為,如果將其設(shè)置為 true,則可以對(duì)對(duì)象列表進(jìn)行排序。

最后兩個(gè)選項(xiàng)確定對(duì)象是否可以被哈?;?,如果你想使用你的 class 的對(duì)象作為字典鍵的話,這是必要的。

python3.8 新特性

  1. :=

    引入賦值表達(dá)式,可以說是Python3.8 中最大的一個(gè)變化了。(:=)形似海象側(cè)牙,也被稱為“海象運(yùn)算符”。賦值表達(dá)式可以在統(tǒng)一表達(dá)式中賦值并返回值,比如下面的代碼,執(zhí)行給變量分配值,并打印這個(gè)值:

     walrus = False
     print(walrus)
    

    可以改為

     print(walrus:=True)
    

    應(yīng)用場(chǎng)景

     inputs = list()
     while (current := input("Write something: ")) != "quit":
         inputs.append(current)
    
  2. 僅位置參數(shù)(Positional-Only Arguments)

    def info(name):
        print(name)

    info(name='python') #python
    info('python')  #python
    
    
但是

    def info(name,/):
        print(name)

    info(name='python'). #error
    info('python') #python
    
通過在 name 之后加入 /,就可以指定 name 為 僅位置參數(shù)。常規(guī)參數(shù)與僅位置參數(shù)結(jié)合使用,可將常規(guī)參數(shù)放在 / 之后:
    
    def info(name , / ,sex=1):
        print(f'name={name},sex={sex}')
    
    info('python')
    info('python',sex=0)
    
還可以通過按 / 和分隔的順序組合僅位置、常規(guī)和僅關(guān)鍵字參數(shù) *,例如下段代碼中,text 是僅位置參數(shù),border 是常規(guī)參數(shù)(值為默認(rèn)值),并且 width 是僅關(guān)鍵字參數(shù)(值為默認(rèn)值):

    def headline(text, /, border="?", *, width=50):
        return f" {text} ".center(width, border)

**??**什么是僅關(guān)鍵字參數(shù)
  1. 詳細(xì)類型

     def double(number: float) -> float:
         return int(2 * number)
     
     
     print(double(3.2))
    

    在此示例中,數(shù)字應(yīng)該是浮點(diǎn)數(shù),并且double()函數(shù)也應(yīng)該返回浮點(diǎn)數(shù)。但是,Python將這些注釋視為提示。它們不會(huì)在運(yùn)行時(shí)強(qiáng)制執(zhí)行:

     from typing import Literal
    
     def draw_line(direction: Literal["horizontal", "vertical"]) -> None:
         if direction == "horizontal":
             ...  # Draw horizontal line
     
         elif direction == "vertical":
             ...  # Draw vertical line
     
         else:
             raise ValueError(f"invalid direction {direction!r}")
     
     draw_line("up")
    
  2. 使用f字符串進(jìn)行更簡單的調(diào)試

    f字符串是在Python 3.6中引入的

     def add(a:int,b:int) ->None:
         print(f'{a = } {b=}')
         print(f'a={a}, b=')
         
         print(f'{a=} {b= :.2f}') # :.2f 可以控制輸出格式
    
     
     add(3,4)
     
     
     def show(s:str) ->None:
         print(f'{s.upper()[::-1] = }')
     show('abc') #s.upper()[::-1] = 'CBA'
    
  3. 新增和改進(jìn)的數(shù)學(xué)和統(tǒng)計(jì)功能

    1. math.prod()

    2. 使用isqrt()來找到平方根的整數(shù)部分

       import math
       
       math.isqrt(15) #3
      
    3. 使用math.dist()找到兩點(diǎn)之間的距離,并通過math.hypot()找到向量的長度:

       import math
       point_1 = (16, 25, 20)
       point_2 = (8, 15, 14)
       math.dist(point_1, point_2)
       math.hypot(*point_1)
      

      這使得使用標(biāo)準(zhǔn)庫更容易處理點(diǎn)和向量。但是,如果要對(duì)點(diǎn)或向量進(jìn)行許多計(jì)算,則應(yīng)簽出NumPy。 統(tǒng)計(jì)模塊還具有幾個(gè)新功能:

      statistics.fmean()計(jì)算浮點(diǎn)數(shù)的平均值。
      statistics.geometric_mean()計(jì)算浮點(diǎn)數(shù)的幾何平均值。
      statistics.multimode()查找序列中最頻繁出現(xiàn)的值。
      statistics.quantiles()計(jì)算用于將數(shù)據(jù)等概率分為n個(gè)連續(xù)區(qū)間的切點(diǎn)。

       import statistics
       data = [9, 3, 2, 1, 1, 2, 7, 9]
       statistics.fmean(data)4.25
      
    4. 在Python 3.8中,有一個(gè)新的statistics.NormalDist類,這使得高斯正態(tài)分布更加方便。

      要查看使用NormalDist的示例,可以對(duì)新的statistics.fmean()和傳統(tǒng)的statistics.mean()的速度進(jìn)行比較:

       import random
       >>> import statistics
       >>> from timeit import timeit
       
       >>> # Create 10,000 random numbers
       >>> data = [random.random() for _ in range(10_000)]
       
       >>> # Measure the time it takes to run mean() and fmean()
       >>> t_mean = [timeit("statistics.mean(data)", number=100, globals=globals())
       ...           for _ in range(30)]
       >>> t_fmean = [timeit("statistics.fmean(data)", number=100, globals=globals())
       ...            for _ in range(30)]
       
       >>> # Create NormalDist objects based on the sampled timings
       >>> n_mean = statistics.NormalDist.from_samples(t_mean)
       >>> n_fmean = statistics.NormalDist.from_samples(t_fmean)
       
       >>> # Look at sample mean and standard deviation
       >>> n_mean.mean, n_mean.stdev
       (0.825690647733245, 0.07788573997674526)
       
       >>> n_fmean.mean, n_fmean.stdev
       (0.010488564966666065, 0.0008572332785645231)
       
       >>> # Calculate the lower 1 percentile of mean
       >>> n_mean.quantiles(n=100)[0]
       0.64450132212
      
  4. 優(yōu)化

    Python 3.8進(jìn)行了一些優(yōu)化,有的讓代碼運(yùn)行得更快,有的優(yōu)化減少了內(nèi)存占用。例如,與Python 3.7相比,在Python 3.8中查找命名元組中的字段要快得多:

**python 簡單了解namedtuple**

namedtuple類位于collections模塊,有了namedtuple后通過屬性訪問數(shù)據(jù)能夠讓我們的代碼更加的直觀更好維護(hù)

namedtuple能夠用來創(chuàng)建類似于元祖的數(shù)據(jù)類型,除了能夠用索引來訪問數(shù)據(jù),能夠迭代,還能夠方便的通過屬性名來訪問數(shù)據(jù)

    from collections import namedtuple
    Friend =namedtuple("Friend",['name','age','email'])
    f1=Friend('giga',38,'gaga@qq.com')
    print(f1)
    print(f1.age)
    print(f1.email)
    f2=Friend(name='jjuu',email='eeee@qw.com',age=15)
    print(f2)
     
    name,age,email=f2
    print(name,age,email)


優(yōu)化體現(xiàn)

    >>>
    >>> import collections
    >>> from timeit import timeit
    >>> Person = collections.namedtuple("Person", "name twitter")>>> raymond = Person("Raymond", "@raymondh")
    
    >>> # Python 3.7
    >>> timeit("raymond.twitter", globals=globals())
    0.05876131607996285
    
    >>> # Python 3.8
    >>> timeit("raymond.twitter", globals=globals())
    0.0377705999400132
    
可以看到,在Python 3.8中在namedtuple上查找.twitter的速度提高了30-40%。從具有已知長度的可迭代對(duì)象初始化列表時(shí),可以節(jié)省一些空間。這樣可以節(jié)省內(nèi)存:

    >>> import sys
    
    >>> # Python 3.7
    >>> sys.getsizeof(list(range(20191014)))
    181719232
    
    >>> # Python 3.8
    >>> sys.getsizeof(list(range(20191014)))
    161528168
    
本例中,該列表在Python 3.8中使用的內(nèi)存比Python 3.7少了大約11%。
  1. 所以,我們必須要更新到 Python3.8 嗎?
    如果你想嘗鮮新功能,那是肯定要升級(jí)的。

    實(shí)際產(chǎn)品的開發(fā)環(huán)境需要升級(jí)到 Python3.8 嗎?首先,如果在 Python3.8 中運(yùn)行 3.7 版本代碼,問題應(yīng)該不會(huì)很大;Python3.8 的beta版本也試用幾個(gè)月了,也解決了不少問題,如果能升級(jí)到Python3.8,肯定也是安全的,還能在新版本中進(jìn)行優(yōu)化。

    如果你想嘗試一下Python3.8,可以閱讀下的文檔,以幫助更好的完成移植

    https://docs.python.org/3.8/whatsnew/3.8.html#porting-to-python-3-8

    還有不能遺漏官方文檔:

    https://www.python.org/downloads/release/python-380/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容