使用 Python 数据类的 10 个令人信服的理由

Python 在3.7 版(PEP 557中引入了数据类。顾名思义,数据类包含数据,使我们能够在类中解锁更多功能。

概述

传统上,我们使用特殊方法初始化类属性并在这些属性之间执行操作。但是,当开发人员花费大量时间编写具有许多属性的特殊方法时,这让他们很头疼。

数据类通过向普通类添加更多功能同时提供更少代码来减少这些问题。

好的,让我们了解为什么 Dataclasses 比普通类更好

1.用更少的代码定义你的类

当我们用__init__方法定义类时,它看起来像这样。

class Student:
    def __init__(self, name, clss, stu_id):
        self.name = name
        self.clss = clss
        self.stu_id = stu_id

但是当你用数据类定义一个类时,你可以在类声明上方使用@dataclass 装饰器。

from dataclasses import dataclass

@dataclass
class Student:
     name: str
     clss: str
     stu_id: int

上述代码中值得注意的地方:

  1. 不在需要初始化函数来初始化类属性。
  2. 我们用类型提示定义每个属性,例如,name: str表示 name 属性应该是字符串类型。

2.设置默认值

你可以为需要的字段提供默认值。

from dataclasses import dataclass


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'

永远不要忘记,没有默认值的字段总是排在第一位。如果你更改顺序,则会引发错误。

3. 表示可读对象

python 数据类支持__repr__因此在打印对象时它提供更好的可读性。

from dataclasses import dataclass


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'


Stu_1 = Student()
print(Stu_1)
# Output: Student(name='Sam', clss='10th', stu_id='10101')

4.创建不可变对象

你可以创建只读对象,你所要做的就是在@dataclass装饰器中将frozen参数设置为True 。

这将防止任何人修改属性。

from dataclasses import dataclass

@dataclass(frozen=True)
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'

stu1 = Student()
print(stu1)
stu1.name = "Jack"

5. 轻松转换元组或字典

借助astuple()asdict()函数,我们可以轻松地将数据类实例转换为元组和字典。

from dataclasses import dataclass, astuple, asdict


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'


Stu_1 = Student()

# tuple conversion
print(astuple(Stu_1))
# Output:('Sam', '10th', '10101')

# Dictionary conversion
print(asdict(Stu_1))
# Output: {'name': 'Sam', 'clss': '10th', 'stu_id': '10101'}

6. 轻松比较对象

如果你检查在标准类声明中具有相同值的两个对象之间的相等性,它会给你 False。

class Student:
    def __init__(self, name, clss, stu_id):
        self.name = name
        self.clss = clss
        self.stu_id = stu_id
        

Stu_1 = Student('Sam', '1oth', '10101')
Stu_2 = Student('Sam', '1oth', '10101')
print(Stu_1 == Stu_2)

# Output: False

这两个对象具有相同的值,但我们的答案是 False,这是因为我们没有实现__eq__方法。

from dataclasses import dataclass


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'


Stu_1 = Student()
Stu_2 = Student()

print(Stu_1 == Stu_2)

# Output: True

当我们用@dataclass 声明类时,这两个对象给出 True,因为它支持 __eq__ 方法。

7. 自定义属性行为

如果你不想在实例化类时初始化属性,可以使用字段函数。

通过使用 field 函数并将initrepr参数设置为False,你可以在不初始化 Percentage 的情况下创建 Student 类。

from dataclasses import dataclass, field


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'
    marks: int = 479
    percentage: str = field(init=False, repr=False)

百分比属性尚不存在。如果你尝试访问它,这将抛出AttributeError。

8. __post_init__

数据类有一个名为 __post_init__ 的特殊方法。

此方法将帮助我们初始化一个依赖于另一个属性值的属性。顾名思义,Python 在 __init__ 方法之后调用 __post_init__ 方法。

回到前面的例子,我们可以看到这个方法是如何初始化百分比属性的。

from dataclasses import dataclass, field


@dataclass
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'
    marks: int = 479
    percentage: str = field(init=False, repr=True)

    def __post_init__(self):
        self.percentage = str((self.marks/500)*100)+'%'


Stu_1 = Student()
print(Stu_1)
# Output: Student(name='Sam', clss='10th', stu_id='10101', marks=479, percentage='95.8%')

print(Stu_1.percentage)
# Output: 95.8%

请注意,字段函数内的repr参数已设置为 True 以使其在打印对象时可见。

9. 比较对象

默认情况下,数据类实现 __eq__ 方法。

要允许不同类型的比较,如__lt__、__lte__、__gt__、__ gte__,你可以将@dataclass装饰器的顺序参数设置为 True。

通过这样做,数据类将按每个字段比较对象,直到找到不相等的值。

from dataclasses import dataclass, field


@dataclass(order=True)
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'
    marks: int = 479
    percentage: str = field(init=False, repr=False)

    def __post_init__(self):
        self.percentage = str((self.marks/500)*100)+'%'


Stu_1 = Student(marks=479)
Stu_2 = Student(marks=470)

print(Stu_1 < Stu_2)

# Output: False

10. 支持可变默认值

在某些情况下,你可能需要创建一个具有默认可变属性的类。

通过使用default_factory你可以创建可变的默认属性。让我们在列表中给 Student 类打分。

from dataclasses import dataclass, field
from typing import List


@dataclass(order=True)
class Student:
    name: str = 'Sam'
    clss: str = '10th'
    stu_id: int = '10101'
    marks: List = field(default_factory=lambda: [94, 88, 99, 100, 98])

请注意,default_factory仅采用零参数可调用,这就是我们使用lambda函数的原因。

数据类使我们能够高效地使用类。

具体来说,该模块有助于:

  • 少写代码。
  • 以可读格式表示对象。
  • 创建不可变对象。
  • 提供 astuple() 和 asdict() 函数将数据类的对象转换为元组和字典。
  • 提供自定义属性行为。
  • 使用 __post_init__ 方法初始化依赖于其他属性的属性。
  • 实施自定义排序和比较。
  • 创建默认的可变属性。

如果你发现我的任何文章对你有帮助或者有用,麻烦点赞或者转发。 谢谢!

相关文章

Python编程语言的优势有哪些?

1.简单易学:Python采用极简主义设计思想,语法简单优雅,不需要很复杂的代码和逻辑,即可实现强大的功能。这使得Python很适合初学者学习,可以帮助初学者快速入门。2.开源免费:Python所有内...

都2023年了,为什么大家还都在吹捧 Python?

2023 年,Python 还可学吗?答案当然是可。近些年间,Python 的火热有目共睹,作为一种功能强大的高级编程语言,在 2018 年的时候它的流行程度就得到了大幅提高。入门人工智能有很多种选择...

不知道学哪种编程语言?Python是首选!

如果编程语言是女生,绝对会让你眼花缭乱,思绪翩翩……有清纯可爱型的,有知性优雅型的,有成熟性感型的,还有如初恋一般甜蜜型的……,那么问题来了,如果你是一个什么都不懂的小白,应该选择哪种语(女)言(人)...

学JAVA好?还是学Python好?

近几年随着Python的迅猛发展,是大多数人产生了迷茫,一方面学Java是行业的主流,另一方面Python发展所带来的巨大红利确实很诱人,再加上Python本身所具备的优点,让学Python也成为大家...

为什么说Python更适合编程入门学习呢?

现在很多新手学生将Python作为了入门级的编程语言学习,在很多高校中也是。为什么高校中很多人不喜欢通过C语言来作为编程入门语言呢?不是说C语言能够帮助初学者更好的掌握计算机的底层原理么?那么用Pyt...

有了python,还需要IFTTT、Zapier这些低代码自动化应用吗?

Claude:在某些情况下,Python编程确实可以取代低代码自动化平台,甚至提供更强大的功能。但两者也有各自的优势,更好的方式是结合使用:Python的优势:1. 更强大的编程能力,可以实现更复杂的...