Python数据类dataclasses的具体使用

作者:

文章目录
  • dataclasses模块提供了一种方便的方法来创建和管理数据对象它可以帮助开发者更容易地创建简单的类,同时提供了一些实用的功能,例如自动实现__init__()、repr()、eq()等方法。 数据容器:如果您需要一个简单的类来存储一些数据,例如配置信息、用户信息、数据记录等,那么使用dataclass是非常合适的。dataclass可以自动为您生成适当的属性和方法,以便您可以轻松地访问和修改数据。 数据对象:如果您的代码需要处理大量的数据对象,例如在数据分析、机器学习、自然语言处理等领域中,那么使用dataclass可以使代码更加清晰易读,减少手动编写大量的属性和方法的重复性工作。 序列化和反序列化:dataclass可以帮助您更轻松地将对象序列化为JSON、XML等格式,并在需要时将其反序列化。这使得处理不同系统之间的数据交换变得更加容易。 数据验证和清理:在某些情况下,您可能需要在将数据存储到数据库或发送到其他系统之前对其进行验证和清理。使用dataclass可以使这个过程更加简单和可靠。
  • from dataclasses import dataclass, field, asdict, astuple from typing import List, Any @dataclass class Book: name: str author: str # extend: Any = ‘hello world’ # 扩展字段 仅做记录 publication: str = field(metadata={“description”: “出版日期”}) num: int = field(default=1, metadata={“description”: “数量”}) price: float = field(default=0.0, metadata={‘currency’: ‘RMB’}) category: List[str] = field(default_factory=list, repr=False, metadata={“description”: “图书类别”}) def __post_init__(self): # 方法来确保书名的每个单词的首字母都是大写的 self.name = self.name.title() self.title = self.name.upper() def is_expensive(self): # 检查一本书是否价格高于100 return self.price > 30.0 def total_amount(self): return self.price * self.num 如何调用 book = Book(name=”Under the sky”, author=”sanxian”, price=37.82, publication=”2022-11-07″, category=[‘武侠’, ‘古风’]) book = Book(**{“name”: “the three body problem”, “author”: “刘慈欣”, “price”: 37.82, “publication”: “2022-12-23”, “category”: [‘科幻’, ‘悬疑’]}) print(book.name, book.author) print(book.title) print(book.is_expensive()) print(book.total_amount()) book.price = 27.5 # 修改价格属性 print(book.is_expensive()) # 输出:True print(asdict(book)) print(astuple(book)) The Three Body Problem 刘慈欣 2022-12-23 37.82 THE THREE BODY PROBLEM True 37.82 False {‘name’: ‘The Three Body Problem’, ‘author’: ‘刘慈欣’, ‘publication’: ‘2022-12-23’, ‘num’: 1, ‘price’: 27.5, ‘category’: [‘科幻’, ‘悬疑’]} (‘The Three Body Problem’, ‘刘慈欣’, ‘2022-12-23’, 1, 27.5, [‘科幻’, ‘悬疑’])
  • 装饰器参数 dataclasses.dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) 参数名称 默认值 是否生成方法 说明 init True __init__ 是否生成 __init__ 方法 repr True __repr__ 是否生成 __repr__ 方法 eq True __eq__ 是否生成 __eq__ 方法 order False <, <=, >, >= 是否生成比较方法 unsafe_hash False __hash__ 是否生成 __hash__ 方法 frozen False 不可变类 是否生成不可变类 init 参数控制是否生成 init 方法。当设置为 True 时,会自动生成 init 方法;当设置为 False 时,不会生成 init 方法。 @dataclass(init=False) class Person: name: str age: int def __init__(self, name: str, age: int): self.name = name self.age = age p = Person(“zhangsan”, 30) print(p.name) # 输出: Alice print(p.age) # 输出: 30 init 被设置为 False,dataclass 不会自动生成 init 方法init 被设置为 True(即默认),该方法接收两个参数 name 和 age,并将存储在实例属性 self.name 和 self.age 中 frozen控制是否创建一个冻结的数据类,即该类的实例在创建后就不可变默认情况下,dataclass 创建的类是可变的。如果你想要创建一个不可变的类,可以设置 frozen=True: from dataclasses import dataclass @dataclass(frozen=True) class Point: x: int y: int p = Point(1, 2) p.x = 3 # 会引发 AttributeError: can’t set attribute from dataclasses import dataclass, field, asdict
  • field 支持的参数 参数 描述 默认值 default 字段的默认值 default_factory 返回字段初始值的函数 init 是否在._init_()方法中使用字段 True repr 是否在._repr_()方法中使用字段 True compare 是否在比较对象时, 包括该字段 True hash 计算hash时, 是否包括字段 True metadata 包含字段信息的映射 compare 默认指定比较,则各个属性依次次进行比较注释:下面仅用年龄进行排序或者排序 @dataclass(order=True) class Person: name: str = field(compare=False) age: int = field(compare=True) height: float = field(compare=False) p1 = Person(name=”A-zhangsan”, age=25, height=156) p2 = Person(name=”B-lisi”, age=18, height=173) p3 = Person(name=”C-wanger”, age=20, height=168) print(p2 > p1) # 输出 True print(sorted([p1,p2, p3])) # 输出按薪资排序的 Person 对象列表 False [ Person(name=’B-lisi’, age=18, height=173), Person(name=’C-wanger’, age=20, height=168), Person(name=’A-zhangsan’, age=25, height=156) ] 控制字段初始化:使用 field() 函数可以更精细地控制字段的初始化: from dataclasses import field @dataclass classPersonWithField: name:str= field(init=False) age:int city:str def__post_init__(self): self.name =f”{self.age} year(s) old in {self.city}” person_with_field =PersonWithField(age=30, city=”New York”) print(person_with_field.name) # 输出: 30 year(s) old in New York 排除某些字段:如果你想在 repr() 方法中排除某些字段,可以使用 repr=False: @dataclass(repr=False) class PersonPartialRepr: name: str age: int = field(repr=False) city: str partial_repr_person = PersonPartialRepr(name=”Alice”, age=30, city=”New York”) print(partial_repr_person) # 输出: Person(name=’Alice’, city=’New York’)
  • 数据记录:dataclass 非常适合用来创建数据记录类,尤其是在你需要存储和处理结构化数据时 @dataclass class SalesRecord: product: str quantity: int price: float timestamp: str record = SalesRecord(product=”Widget”, quantity=100, price=19.99, timestamp=”2023-04-01T12:00:00″) 配置文件:dataclass 也可以用来创建配置类,使得配置更加直观和易于管理。 from typing importList @dataclass classConfig: database:str port:int debug:bool=False tables:List[str]= field(default_factory=list) config =Config(database=”mydb”, port=5432, debug=True, tables=[“users”,”products”]) 领域驱动设计:在领域驱动设计中,dataclass 可以用来表示聚合根、实体和值对象。 @dataclass(frozen=True) classUser: id:int username:str email:str @dataclass classUserBuilder: id:int=None username:str=None email:str=None def build(self): if self.id is None or self.username is None or self.email is None: raiseValueError(“All fields are required”) returnUser(id=self.id, username=self.username, email=self.email) 数据验证:结合第三方库如 Pydantic,dataclass 可以用于数据验证。 from pydantic import BaseModel @dataclass class UserInput(BaseModel): name: str age: int city: str input_data = UserInput(name=”Bob”, age=25, city=”Los Angeles”) 到此这篇关于Python数据类dataclasses的具体使用的文章就介绍到这了,更多相关python dataclasses内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Python中pandas dataframe删除一行或一列:drop函数详解 python pandas dataframe 按列或者按行合并的方法 Python Pandas批量读取csv文件到dataframe的方法 python中关于时间和日期函数的常用计算总结(time和datatime) 使用Python向DataFrame中指定位置添加一列或多列的方法 python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除) 在 Python 中创建DataFrame的方法 python DataFrame获取行数、列数、索引及第几行第几列的值方法
  • 目录
    • 一、场景
    • 二、基础用法
    • 三、中级用法
    • 四、其它用法
    • 五、使用场景举例

    dataclasses模块提供了一种方便的方法来创建和管理数据对象
    它可以帮助开发者更容易地创建简单的类,同时提供了一些实用的功能,例如自动实现__init__()、repr()、eq()等方法。

    • 数据容器:如果您需要一个简单的类来存储一些数据,例如配置信息、用户信息、数据记录等,那么使用dataclass是非常合适的。dataclass可以自动为您生成适当的属性和方法,以便您可以轻松地访问和修改数据。
    • 数据对象:如果您的代码需要处理大量的数据对象,例如在数据分析、机器学习、自然语言处理等领域中,那么使用dataclass可以使代码更加清晰易读,减少手动编写大量的属性和方法的重复性工作。
    • 序列化和反序列化:dataclass可以帮助您更轻松地将对象序列化为JSON、XML等格式,并在需要时将其反序列化。这使得处理不同系统之间的数据交换变得更加容易。
    • 数据验证和清理:在某些情况下,您可能需要在将数据存储到数据库或发送到其他系统之前对其进行验证和清理。使用dataclass可以使这个过程更加简单和可靠。

    from dataclasses import dataclass, field, asdict, astuple
    from typing import List, Any
    
    @dataclass
    class Book:
        name: str
        author: str
        # extend: Any = 'hello world'   # 扩展字段 仅做记录
        publication: str = field(metadata={"description": "出版日期"})
        num: int = field(default=1, metadata={"description": "数量"})
        price: float = field(default=0.0, metadata={'currency': 'RMB'})
        category: List[str] = field(default_factory=list, repr=False, metadata={"description": "图书类别"})
    
        def __post_init__(self):
            # 方法来确保书名的每个单词的首字母都是大写的
            self.name = self.name.title()
            self.title = self.name.upper()
    
        def is_expensive(self):
            # 检查一本书是否价格高于100
            return self.price > 30.0
    
        def total_amount(self):
    
            return self.price * self.num
    

    如何调用

    book = Book(name="Under the sky", author="sanxian", price=37.82, publication="2022-11-07", category=['武侠', '古风'])
    book = Book(**{"name": "the three body problem", "author": "刘慈欣", "price": 37.82, "publication": "2022-12-23", "category": ['科幻', '悬疑']})
    print(book.name, book.author)
    print(book.title)
    
    print(book.is_expensive())
    print(book.total_amount())
    
    book.price = 27.5  # 修改价格属性
    print(book.is_expensive())  # 输出:True
    
    print(asdict(book))
    print(astuple(book))
    
    The Three Body Problem 刘慈欣 2022-12-23 37.82
    THE THREE BODY PROBLEM
    True
    37.82
    False
    {'name': 'The Three Body Problem', 'author': '刘慈欣', 'publication': '2022-12-23', 'num': 1, 'price': 27.5, 'category': ['科幻', '悬疑']}
    ('The Three Body Problem', '刘慈欣', '2022-12-23', 1, 27.5, ['科幻', '悬疑'])
    

    装饰器参数 dataclasses.dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)

    参数名称 默认值 是否生成方法 说明
    init True __init__ 是否生成 __init__ 方法
    repr True __repr__ 是否生成 __repr__ 方法
    eq True __eq__ 是否生成 __eq__ 方法
    order False <, <=, >, >= 是否生成比较方法
    unsafe_hash False __hash__ 是否生成 __hash__ 方法
    frozen False 不可变类 是否生成不可变类

    init 参数控制是否生成 init 方法。当设置为 True 时,会自动生成 init 方法;当设置为 False 时,不会生成 init 方法。

    @dataclass(init=False)
    class Person:
        name: str
        age: int
    
        def __init__(self, name: str, age: int):
            self.name = name
            self.age = age
    
    p = Person("zhangsan", 30)
    print(p.name) # 输出: Alice
    print(p.age)  # 输出: 30
    

    init 被设置为 False,dataclass 不会自动生成 init 方法
    init 被设置为 True(即默认),该方法接收两个参数 name 和 age,并将存储在实例属性 self.name 和 self.age 中

    frozen控制是否创建一个冻结的数据类,即该类的实例在创建后就不可变
    默认情况下,dataclass 创建的类是可变的。
    如果你想要创建一个不可变的类,可以设置 frozen=True:

    from dataclasses import dataclass
    
    @dataclass(frozen=True)
    class Point:
        x: int
        y: int
    
    p = Point(1, 2)
    p.x = 3  # 会引发 AttributeError: can't set attribute
    
    from dataclasses import dataclass, field, asdict
    

    field 支持的参数

    参数 描述 默认值
    default 字段的默认值
    default_factory 返回字段初始值的函数
    init 是否在._init_()方法中使用字段 True
    repr 是否在._repr_()方法中使用字段 True
    compare 是否在比较对象时, 包括该字段 True
    hash 计算hash时, 是否包括字段 True
    metadata 包含字段信息的映射

    compare 默认指定比较,则各个属性依次次进行比较
    注释:下面仅用年龄进行排序或者排序

    @dataclass(order=True)
    class Person:
        name: str = field(compare=False)
        age: int = field(compare=True)
        height: float = field(compare=False)
    
    p1 = Person(name="A-zhangsan", age=25, height=156)
    p2 = Person(name="B-lisi", age=18, height=173)
    p3 = Person(name="C-wanger", age=20, height=168)
    
    print(p2 > p1)  # 输出 True
    print(sorted([p1,p2, p3]))  # 输出按薪资排序的 Person 对象列表
    
    False
    [
    	Person(name='B-lisi', age=18, height=173), 
    	Person(name='C-wanger', age=20, height=168), 
    	Person(name='A-zhangsan', age=25, height=156)
    ]
    

    控制字段初始化:使用 field() 函数可以更精细地控制字段的初始化:

    from dataclasses import field
    
    @dataclass
    classPersonWithField:
        name:str= field(init=False)
        age:int
        city:str
    
    def__post_init__(self):
            self.name =f"{self.age} year(s) old in {self.city}"
    
    person_with_field =PersonWithField(age=30, city="New York")
    print(person_with_field.name)  # 输出: 30 year(s) old in New York
    

    排除某些字段:如果你想在 repr() 方法中排除某些字段,可以使用 repr=False:

    @dataclass(repr=False)
    class PersonPartialRepr:
        name: str
        age: int = field(repr=False)
        city: str
    
    partial_repr_person = PersonPartialRepr(name="Alice", age=30, city="New York")
    print(partial_repr_person)  # 输出: Person(name='Alice', city='New York')
    

    数据记录:dataclass 非常适合用来创建数据记录类,尤其是在你需要存储和处理结构化数据时

    @dataclass
    class SalesRecord:
        product: str
        quantity: int
        price: float
        timestamp: str
    
    record = SalesRecord(product="Widget", quantity=100, price=19.99, timestamp="2023-04-01T12:00:00")
    

    配置文件:dataclass 也可以用来创建配置类,使得配置更加直观和易于管理。

    from typing importList
    
    @dataclass
    classConfig:
        database:str
        port:int
        debug:bool=False
        tables:List[str]= field(default_factory=list)
    
    config =Config(database="mydb", port=5432, debug=True, tables=["users","products"])
    

    领域驱动设计:在领域驱动设计中,dataclass 可以用来表示聚合根、实体和值对象。

    @dataclass(frozen=True)
    classUser:
    	id:int
    	username:str
    	email:str
    
    @dataclass
    classUserBuilder:
    	id:int=None
    	username:str=None
    	email:str=None
    
    def build(self):
    	if self.id is None or self.username is None or self.email is None:
    		raiseValueError("All fields are required")
    	returnUser(id=self.id, username=self.username, email=self.email)
    

    数据验证:结合第三方库如 Pydantic,dataclass 可以用于数据验证。

    from pydantic import BaseModel
    
    @dataclass
    class UserInput(BaseModel):
        name: str
        age: int
        city: str
    
    input_data = UserInput(name="Bob", age=25, city="Los Angeles")
    

    到此这篇关于Python数据类dataclasses的具体使用的文章就介绍到这了,更多相关python dataclasses内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Python中pandas dataframe删除一行或一列:drop函数详解
    • python pandas dataframe 按列或者按行合并的方法
    • Python Pandas批量读取csv文件到dataframe的方法
    • python中关于时间和日期函数的常用计算总结(time和datatime)
    • 使用Python向DataFrame中指定位置添加一列或多列的方法
    • python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
    • 在 Python 中创建DataFrame的方法
    • python DataFrame获取行数、列数、索引及第几行第几列的值方法

    站内搜索