簡體   English   中英

如何在不注釋類型的情況下添加數據類字段?

[英]How to add a dataclass field without annotating the type?

當數據類中有一個類型可以是任何類型的字段時,如何省略注釋?

@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck = object()
    fav_word: str = 'potato'

看起來上面的代碼實際上並沒有為fav_duck創建一個字段。 它只是使它成為一個普通的舊 class 屬性。

>>> Favs()
Favs(fav_number=80085, fav_word='potato')
>>> print(*Favs.__dataclass_fields__)
fav_number fav_word
>>> Favs.fav_duck
<object at 0x7fffea519850>

數據類裝飾器通過查找__annotations__名稱來檢查類以查找字段。 它是存在的注釋,使得該字段 ,因此,您需要一個注釋。

但是,您可以使用通用的:

@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck: 'typing.Any' = object()
    fav_word: str = 'potato'

類型提示是 Python 的可選功能。這也意味着,使用@dataclass不需要您定義類型。

在注釋中你可以寫很多東西。 如果您不想檢查它們,則不會檢查它們。 這些示例有效:

@dataclass
class ColoredObject:
    color : "" 
    name : ""
@dataclass
class ColoredObject:
    color : ... 
    name : ...
@dataclass
class ColoredObject:
    color : True 
    name : True
@dataclass
class ColoredObject:
    color : object
    name : object
@dataclass
class ColoredObject:
    color : None
    name : None

我在這里列出了很多選項,以便您可以決定是否喜歡其中的一些選項。 如何使用代碼注釋由您決定。

對於比 Python 更習慣靜態類型語言的人來說,這可能是一種尷尬的風格。 為此,它看起來像是在濫用空字符串或橢圓 object。 這是真的。 但請記住,代碼可讀性在編程中也很重要。 有趣的是,如果您編寫... ,您的代碼的大多數讀者會憑直覺理解,甚至不知道存在類似橢圓 object 的東西。

當然,如果您不想讓喜歡類型提示的人感到困惑,或者如果您想要使用期望正確類型提示的工具,則必須就此達成協議。

typing.Any的解決方案我沒有列出。 當然這是一個很好的解決方案。 但是類型是 Python 的一個可選特性。這也意味着知道有類似typing.Any的東西是可選的知識。

如果您能夠在文件頂部添加from __future__ import annotations ,這會將文件中的所有注釋轉換為字符串,以便隨后對它們進行延遲評估 這對於定義不需要在運行時解析的注釋非常有用。

例如,一種為字段使用簡短類型注釋 ( _ ) 的方法:

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING


# added to silence any IDE warnings (i.e. PyCharm)
if TYPE_CHECKING:
    _ = object


@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck: _ = object()
    fav_word: str = 'potato'


print(Favs())

印刷:

Favs(fav_number=80085, fav_duck=<object object at 0x11b754ad0>, fav_word='potato')

如果您不想或不能使用__future__導入(即,如果您使用的是 Python 3.6 或更低版本,或者想要消除 IDE 的“未解析引用”警告),您始終可以預先為類型注釋定義一個值:

from dataclasses import dataclass


# or: 
#   = ...
_ = object


@dataclass
class Favs:
    fav_number: int = 80085
    fav_duck: _ = object()
    fav_word: str = 'potato'


print(Favs())

根據PEP 557定義數據類的含義,

dataclass裝飾器檢查類以查找字段。 字段定義為__annotations__標識的任何變量。 也就是說,具有類型注釋的變量。

這是說,這個問題的前提下(如“我如何使用dataclass與沒有類型注釋字段)必須被拒絕。在上下文中的術語‘場’ dataclass的必要條件是屬性有一個類型的注釋通過定義。

請注意,使用類似於typing.Any的泛型類型注釋。任何與具有未注釋屬性的注釋不同,因為該屬性將出現在__annotations__

最后,輔助函數make_dataclass將自動使用typing.Any用於在僅提供屬性名稱的情況下的類型注釋,並且在PEP中也提到了一個示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM