1. 程式人生 > 資料庫 >阿里架構師純手寫java面試寶典:spring/Redis/資料/Kafka/微服務,就問還有誰?

阿里架構師純手寫java面試寶典:spring/Redis/資料/Kafka/微服務,就問還有誰?

此文轉載自:https://blog.csdn.net/lianshaohua/article/details/110199175#commentBox

Python3.9 剛剛釋出不久,Python3.10 的第二個 alpha 版本也已於 11 月初發布。透過這個版本,我們或許可以一窺 Python 的未來改變。

Python3.10 第二個 alpha 版本的新功能包括以下三大部分:

  • 型別註釋擴充套件

  • 為什麼型別註釋很重要

  • 新方法和行為

Python3.9 版本對型別提示與註釋進行了徹底的修改和清理。Python3.10 版本似乎延續了這一趨勢,Python3.10 alpha 2 版本將型別註釋功能進行了擴充套件。

型別註釋的延遲評估

型別註釋的評估始終在函式定義時執行,這意味著型別註釋以自上而下的方式逐行進行評估。這看似合乎邏輯,但存在兩個問題:

引用尚未定義的型別(前向引用)的型別提示無效,必須以字串形式表示。例如應該是「“int”」而不是「int」(儘管這僅適用於自定義型別,而不是內建 / 預定義型別)。
由於需要執行型別提示,模組匯入的速度減慢。

因此,註釋將被儲存在 annotations,然後進行集中評估,即允許前向引用並首先執行模組匯入(以減少初始化時間)。

Union 操作符型別

Python 3.10 引入了 | 操作符。在註釋資料型別時,可以使用 | 作為 OR。例如,存在一個預計為 int 或 float 的變數,我們可以將其寫作 int | float:

def f(x: *int | float*) -> float:
return x * 3.142
f(1)  # pass
f(1.5)  # pass
f('str')  # linter will show annotation error

在 3.10 之前的版本中,等效運算子使用 type.Union 方法進行編寫,例如 Union[int, float]。

TypeAlias 註釋

回到前向引用問題,避免前向引用的常見解決方案是將它們作為字串寫入。

但是,將型別作為字串編寫,會在將這些型別分配給變數時出現問題,因為 Python 假設字串文字型別註釋只是一個字串。

在使用型別註釋的地方使用該型別註釋變數將返回錯誤。例如:
MyType = “ClassName” # ClassName is our type annotation
def foo() -> MyType:

我們正在嘗試使用 MyType 作為型別的別名(alias),但是 MyType 將被讀取為字串值,而不是類型別名。

只要在後面的程式碼中定義了 ClassName,這就是有效的。目前,這將引發註釋錯誤。

為了解決這個問題,該版本添加了一個顯式地將 MyType 識別為類型別名的方法:

from typing_extensions import TypeAlias
MyType: TypeAlias = "ClassName"
def foo() -> MyType:
    ...
OR
MyType: TypeAlias = ClassName # if we have defined ClassName already
def foo() -> MyType:
    ...

為什麼型別註釋很重要

Python 的強大之處在於它易於使用和掌握,原因之一就是我們不需要在整個程式碼中顯式地定義型別。

這看似違背常理,但允許開發人員定義型別可以極大地增強程式碼庫的可讀性和可維護性。例如從 transformers 庫的原始碼中提取如下內容:

def get_default_model(targeted_task: Dict, framework: Optional[str], task_options: Optional[Any]) -> str:
    ...

class DefaultArgumentHandler(ArgumentHandler):
    ...
    @staticmethod
def handle_kwargs(kwargs: Dict) -> List:
        ...

    @staticmethod
def handle_args(args: Sequence[Any]) -> List[str]:

即使沒有上下文,我們也可以讀取這些程式碼,並瞭解應該向這些函式、類和方法提供哪些資料,以及應該返回哪些資料型別。

在複雜的程式碼庫(甚至是簡單的程式碼庫)中,型別註釋可以極大地提高可讀性。同時,並不是每個開發者都想(或需要)使用型別註釋,因此可選的、無異常的功能可以達到完美的平衡。

新方法和實現

除了型別註釋方面的更改之外,3.10 alpha 2 版本對其他核心功能也進行了一些更新。

為 Zip 新增等長標記

第一個是 PEP 618,它為 zip() 函式添加了一個可選的 strict 標記。設定 strict = True,如果 zip 的兩個輸入長度不等,則會引發錯誤。

例1
x=[1,2,3,4,5,6]
y=[1,2,3,4]
z=zip(x,y)
print(list(z))
## [(1,1),(2,2),(3,3),(4,4)]
例2
x=[1,2,3,4,5,6]
y=[1,2,3,4]
z=zip(x,y,strict=True)
print(list(z))
## ValueError: zip() argument 2 is shorter than argument 1

例1無 strict=True 標記,沒有引發錯誤,並且較長的列表被截斷用於建立壓縮生成器。例2設定 strict = True,就會引發錯誤。

整數的位計數

也叫做「總體計數」(population count)。這一新方法允許計算整數二進位制表示中 1 的個數,只需寫 int.bit_count() 即可:

for x in[0,1,2,3,10,11,12,100,101,102]:
  print(f"{x}={x.bit_count()}")
## 0=0
## 1=1
## 2=1
## 3=2
## 10=2
## 11=3
...
## 102=4

字典檢視對映

三種字典方法 dict.keys()、dict.values() 和 dict.items() 返回字典的不同檢視。現在,將 mapping 屬性新增到每個檢視物件。

x={'hello':0,'world':1}
keys=x.keys()
print(keys)
## dict_keys(['hello','world'])
print(keys.mapping)
## {'hello':0,'world':1}

這一新屬性是 types.MappingProxyType 物件,用來包裝原始字典。如果在檢視上呼叫它,則返回原始字典。