程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

了解python dataclasses

hfteth 2025-08-02 18:19:08 技术文章 6 ℃

了解python dataclasses

, <> 6 分钟阅读

Python 3.7 版本引入了一个新功能:。dataclasses

作为参考,类基本上是创建对象的蓝图。类的一个例子可以是一个国家,我们将使用该类来创建各种实例,例如摩纳哥和冈比亚。Country

初始化值时,提供给构造函数的属性(如人口、语言等)将复制到每个对象实例中:

class Country:
    def __init__(self, name: str, population: int, continent: str, official_lang: str):
        self.name = name
        self.population = population
        self.continent = continent
        self.official_lang = official_lang


smallestEurope = Country("Monaco", 37623, "Europe")
smallestAsia= Country("Maldives", 552595, "Asia")
smallestAfrica= Country("Gambia", 2521126, "Africa") 

如果您曾经使用过Java和Python等编程语言的面向对象编程(OOP),那么您应该已经熟悉类。

然而,A附带了已经实现的基本类功能,减少了编写代码所花费的时间。dataclass

在本文中,我们将进一步深入研究 Python 中是什么,如何操作对象字段,如何排序和比较等等。dataclassesdataclasses

请注意,由于这是在 Python 3.7 中发布的,因此您必须在本地计算机上安装最新版本的 Python 才能使用它。

什么是Python?dataclass

如前所述,Python 与普通类非常相似,但具有实现的类功能,可显著减少编写所需的样板代码量。dataclasses

这种样板的一个例子是方法。__init__

在类示例中,您可以观察到我们必须手动定义方法,该方法在初始化类时被调用。现在,对于您定义的每个普通类,您都需要提供此函数,这意味着您必须编写大量重复的代码。Country__init__

Python 附带了已经定义的此方法。因此,您可以编写相同的类,而无需手动定义构造函数。dataclassCountry

在后台,在使用新属性初始化对象时调用此方法。@dataclass



请注意,这不是默认提供的唯一方法。其他实用工具方法,如(表示)、(小于)、(大于)、(等于)和许多其他方法也默认实现。
__init____repr____lt____gt____eq__

使用普通的 Python 类

在 Python 中使用普通类时,我们有更长的代码来实现基本方法。

再次考虑class。在下面的代码块中,您可以看到几个方法,从方法开始。此方法初始化实例上的国家/地区名称、人口计数、洲和官方语言等属性。Country__innit__Country

__repr__返回类实例的字符串表示形式。这将以字符串形式打印每个类实例的属性。

_lt_比较两个实例的总体,如果当前实例的总体较少,则返回,如果它们都具有相同的总体计数,则返回:CountryTrue_eq_True

class Country:
    def __init__(self, name: str, population: int, continent: str, official_lang: str="English" ):
        self.name = name
        self.population = population
        self.continent = continent
        self.official_lang= official_lang

   def __repr__(self):
        return(f"Country(name={self.name},
            population={self.population}, continent={self.continent},
            official_lang={self.official_lang})")

   def __lt__(self, other):
        return self.population < other.population

   def __eq__(self, other):
        return self.population == other.population


smallestAfrica= Country("Gambia", 2521126, "Africa", "English")
smallestEurope = Country("Monaco", 37623, "Europe", "French")
smallestAsia1= Country("Maldives", 552595, "Asia", "Dhivehi")
smallestAsia2= Country("Maldives", 552595, "Asia", "Dhivehi")


print(smallestAfrica) 
# Country(name='Gambia', population=2521126, continent='Africa', #official_lang='English')

print(smallestAsia < smallestAfrica) # True
print(smallestAsia > smallestAfrica) # False

使用蟒pyton dataclass

要在代码中使用 Python,只需导入模块并在类之上注册装饰器即可。这会自动将基类功能注入到我们的类中。dataclass@dataclass

在下面的示例中,我们将创建相同的类,但代码要少得多:Country

from dataclasses import dataclass

@dataclass(order=True)
class Country:
     name: str
     population: int
     continent: str
     official_lang: str

smallestAfrica= Country("Gambia", 2521126, "Africa", "English")
smallestEurope = Country("Monaco", 37623, "Europe", "French")
smallestAsia1= Country("Maldives", 552595, "Asia", "Dhivehi")
smallestAsia2= Country("Maldives", 552595, "Asia", "Dhivehi")

# Country(name='Gambia', population=2521126, continent='Africa', #official_lang='English')

print(smallestAsia1 == smallestAsia2) # True
print(smallestAsia < smallestAfrica) # False

请注意,我们没有在 ;我们刚刚定义了字段。dataclass

我们还省略了像 和 这样的帮助程序。尽管省略了这些方法,但该类仍然正常运行。repr__eq__

请注意,对于小于 (),使用默认方法来比较对象。在本文的后面,我们将学习如何自定义对象比较以获得更好的结果。<dataclass

使用函数操作对象字段field()

该模块还提供了一个名为 .此函数使您可以对类字段进行根深蒂固的控制,从而可以根据需要操作和自定义它们。dataclassfield()

例如,我们可以在调用表示方法时排除该字段,方法是向其传递参数并将值设置为 :continentreprfalse

from dataclasses import dataclass, field

@dataclass
class Country:
     name: str
     population: int
     continent: str = field(repr=False) # omits the field
     official_lang: str

smallestEurope = Country("Monaco", 37623, "Europe", "French")

print(smallestEurope)

# Country(name='Monaco', population=37623, official_lang='French') 

然后,此代码在 CLI 中输出:

默认情况下,始终设置为reprTrue

下面是一些其他参数,可以由 采用。field()

init参数

参数传递以指定在初始化期间是否应将属性作为参数包含在构造函数中。如果将字段设置为 ,则必须在初始化期间省略该属性。否则,将抛出:initinnit=FalseTypeError

from dataclasses import dataclass, field

@dataclass
class Country:
     name: str
     population: int  
     continent: str
     official_lang: str = field(init=False) #Do not pass in this attribute in the constructor argument  


smallestEurope = Country("Monaco", 37623, "Europe", "English") #But you did, so error!

print(smallestEurope)

然后,此代码在 CLI 中输出:

default参数

传递该参数以指定字段的默认值,以防在初始化期间未提供值:default

from dataclasses import dataclass, field

@dataclass
class Country:
     name: str
     population: int  
     continent: str
     official_lang: str = field(default="English") # If you ommit value, English will be used


smallestEurope = Country("Monaco", 37623, "Europe") #Omitted, so English is used

print(smallestEurope)

然后,此代码在 CLI 中输出:

repr参数

参数传递以指定字段是否应从字符串表示形式中包含 () 或排除 (),由该方法生成:reprrepr=Truerepr=False__repr__

from dataclasses import dataclass, field

@dataclass
class Country:
     name: str
     population: int  
     continent: str
     official_lang: str = field(repr=False) # This field will be excluded from string representation


smallestEurope = Country("Monaco", 37623, "Europe", "French") 

print(smallestEurope)

然后,此代码在 CLI 中输出:

初始化后修改字段__post_init__

该方法在初始化后立即调用。换句话说,在对象收到其字段的值(如 、、 和 )之后调用它。
__post_init__namecontinentpopulationofficial_lang

例如,我们将使用该方法根据该国的官方语言确定我们是否要迁移到该国家/地区:

from dataclasses import dataclass, field

@dataclass
class Country:
     name: str
     population: int
     continent: str = field(repr=False) # Excludes the continent field from string representation
     will_migrate: bool = field(init=False) # Initialize without will_migrate attribute
     official_lang: str = field(default="English") # Sets default language. Attributes with default values must appear last


     def __post_init__(self):
           if self.official_lang == "English":
                 self.will_migrate == True
           else:
                 self.will_migrate == False 

对象使用值初始化后,我们执行检查以查看字段是否设置为 从内部 .如果是这样,我们必须将属性设置为 .否则,我们将其设置为 .
official_langEnglishpost_initwill_migratetruefalse

排序和比较dataclassessort_index

的另一个功能是能够创建自定义顺序来比较对象和对对象列表进行排序。dataclasses

例如,我们可以通过人口数量比较两个国家。换句话说,我们想说一个国家大于另一个国家,当且仅当其人口数量大于另一个国家:

from dataclasses import dataclass, field

@dataclass(order=True)
class Country:
     sort_index: int = field(init=False)
     name: str
     population: int = field(repr=True)
     continent: str 
     official_lang: str = field(default="English") #Sets default value for official language



     def __post_init__(self):
           self.sort_index = self.population

smallestEurope = Country("Monaco", 37623, "Europe")
smallestAsia= Country("Maldives", 552595, "Asia")
smallestAfrica= Country("Gambia", 2521126, "Africa") 

print(smallestAsia < smallestAfrica) # True
print(smallestAsia > smallestAfrica) # False

要在 Python 中启用比较和排序,您必须将属性传递给 with 值。这将启用默认的比较功能。dataclassorder@dataclasstrue

由于我们要按总体计数进行比较,因此我们必须在初始化后从方法内部将字段传递给属性。
populationsort_index__post_innit__

您还可以使用特定字段对对象列表进行排序。例如,我们必须按人口数量对国家/地区列表进行排序:sort_index

from dataclasses import dataclass, field

@dataclass(order=True)
class Country:
     sort_index: int = field(init=False)
     name: str
     population: int = field(repr=True)
     continent: str 
     official_lang: str = field(default="English")



     def __post_init__(self):
           self.sort_index = self.population



europe = Country("Monaco", 37623, "Europe", "French")
asia = Country("Maldives", 552595, "Asia", "Dhivehi")
africa = Country("Gambia", 2521126, "Africa", "English")
sAmerica = Country("Suriname", 539000, "South America", "Dutch")
nAmerica = Country("St Kits and Nevis", 55345, "North America", "English")
oceania = Country("Nauru", 11000, "Oceania", "Nauruan")  

mylist = [europe, asia, africa, sAmerica, nAmerica, oceania]
mylist.sort()

print(mylist) # This will return a list of countries sorted by population count, as shown below

然后,此代码在 CLI 中输出:

不想被篡改?您可以通过简单地将值传递给装饰器来冻结类:dataclassfrozen=True

from dataclasses import dataclass, field

@dataclass(order=True, frozen=True)
class Country:
     sort_index: int = field(init=False)
     name: str
     population: int = field(repr=True)
     continent: str 
     official_lang: str = field(default="English")



     def __post_init__(self):
           self.sort_index = self.population

总结

Python 是一个非常强大的功能,它大大减少了类定义中的代码量。该模块提供了大多数已实现的基本类方法。您可以自定义 中的字段并限制某些操作。dataclassdataclass

Tags:

最近发表
标签列表