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

liftword5个月前 (01-06)技术文章40

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所有内...

一次Java和Python的简单且直观的比较

我的主要开发语言是Java,并且多年来主要项目基本都是使用Vue+Springboot来实现客户业务。最近几年,Python绝对是成长最快的语言,用户量暴增,已经成了很多大学的主要编程课程了。同时,码...

Python介绍及其特点

Python介绍Python是编程语言是1989年由荷兰程序员吉多·范罗苏姆发明的,于1991年发布第一个版本。Python源代码遵循GPL协议(自由软件基金协会发行的计算机软件协议证书)。Pytho...

Excel支持Python了,你先冷静一下

HI,大家好,我是星光。今天给大家聊一下这段时间很火热的Python in Excel,希望大家看完之后冷静一下,不要再天天催更了。本期推文主要回答大家以下几个问题:1,什么是Python in Ex...

Python有哪些应用场景?

同步视频讲解:xpython.com.cn/ch/ttPython的应用场景非常广泛,下面介绍10个应用场景以及Python的解决方案:1. 原型化开发在开发实际项目中,我们常常采用原型化的开发方法,...