标签: python-dataclasses

在 Flask-SQLAlchemy 模型类中使用数据类装饰器?

我编写了一个 Flask-SQLAlchemy 模型类,如下所示(来自此参考):

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

class User(db.Model):
    
    __tablename__ = 'user'
    
    user_id = db.Column(db.Integer, primary_key=True)
    user_url = db.Column(db.String(2083), unique=True, nullable=False)
    username = db.Column(db.String(80), unique=True, nullable=False)
    avatar_url = db.Column(db.String(2083), unique=True, nullable=False)
    
    def __init__(self, user_id, user_url, username, avatar_url):
    
        self.user_id = user_id
        self.user_url = user_url
        self.username = username
        self.avatar_url = avatar_url
Run Code Online (Sandbox Code Playgroud)

但是,我想使用dataclass装饰器(参考)来简化其实现,特别是避免重写__init__dunder 方法,并更容易地将此​​类序列化为 Python dict

但是,将此类的实现更改为:

@dataclass
class User(db.Model):

    __tablename__ = 'user'

    user_id: …
Run Code Online (Sandbox Code Playgroud)

python sqlalchemy flask-sqlalchemy python-dataclasses

4
推荐指数
1
解决办法
2385
查看次数

如何从数据类中提取属性或字段名称?

我有一个数据类,说Car

from dataclasses import dataclass

@dataclass
class Car:
    make: str
    model: str
    color: hex
    owner: Owner
Run Code Online (Sandbox Code Playgroud)

如何在列表中提取数据类的属性或字段?,例如

attributes = ['make', 'model', 'color', 'owner']
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

4
推荐指数
1
解决办法
4205
查看次数

使用 dataclasses.MISSING 作为 Python 数据类的可选参数值?

我想让set参数可选,但仍然允许None为有效值。根据文档,它建议dataclasses.MISSING可以使用默认值来帮助实现这一点。

如上所示,MISSINGvalue是一个哨兵对象,用于检测用户是否提供了某些参数。使用此标记是因为None它对于某些具有不同含义的参数来说是有效值。任何代码都不应直接使用该MISSING值。

但通过如下使用:

import dataclasses
from dataclasses import dataclass, field

@dataclass
class Var:
    get: list
    set: list = dataclasses.MISSING

    def __post_init__(self):
        if self.set is dataclasses.MISSING:
            self.set = self.get

 print(Var(get=['Title']))  
Run Code Online (Sandbox Code Playgroud)

我收到错误:

Traceback (most recent call last):
File "main.py", line 31, in <module>
print(Var(get=['Title']))
TypeError: __init__() missing 1 required positional argument: 'set'
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

4
推荐指数
1
解决办法
4971
查看次数

如何处理将camelCase json 映射到snake_case python 数据类字段名称?

我正在使用 Python 与 Web api 交互,其中 json 响应中的键采用驼峰命名法。我的Python模型是数据类,其字段名称是snake_case。当我从 json 转换为 model 时,反之亦然,名称显然不匹配。

作为参考,我使用 asdict 函数将模型转换为 json。

def to_json(self):
  return asdict(
    self, 
    dict_factory=lambda _fields: {
      key: value for (key, value) in _fields if value is not None
    }
  )
Run Code Online (Sandbox Code Playgroud)

从 json 转换为 model 的代码稍微复杂一些,但也依赖于字段名称来映射到 json 键。这两种转换都足够通用,可以适用于我的所有模型,而无需为每个单独的模型(30 个左右)创建转换器。

在这种情况下,使用 comeCase 作为我的模型字段名称是否是常见做法(即使它不符合标准命名实践)?

我无法修改 api,无论好坏,键名称将始终采用驼峰命名法。

python python-dataclasses

4
推荐指数
1
解决办法
3932
查看次数

我如何输入提示初始化参数与数据类中的字段相同?

假设我有一个自定义用例,我需要动态创建或定义__init__数据类的方法。

例如,假设我需要像这样装饰它,@dataclass(init=False)然后修改__init__()方法以采用关键字参数,例如**kwargs. 但是,在kwargs对象中,我仅检查已知数据类字段是否存在,并相应地设置这些属性(下面的示例)

我想向我的 IDE (PyCharm) 键入提示,修改后的内容__init__仅接受列出的数据类字段作为参数或关键字参数。我不确定是否有办法解决这个问题,使用typing库或其他方式。我知道 PY3.11 已计划进行数据类转换,这可能会也可能不会满足我的要求(我的直觉是否定的)。

这是我正在使用的示例代码,这是一个基本案例,说明了我遇到的问题:

from dataclasses import dataclass


# get value from input source (can be a file or anything else)
def get_value_from_src(_name: str, tp: type):
    return tp()  # dummy value


@dataclass
class MyClass:
    foo: str
    apple: int

    def __init__(self, **kwargs):
        for name, tp in self.__annotations__.items():
            if name in kwargs:
                value = kwargs[name]
            else:
                # here …
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses python-typing

4
推荐指数
1
解决办法
1647
查看次数

使用函数初始化数据类实例

我正在尝试创建一个数据类来将所有相关数据存储在单个对象中。如何初始化一个数据类实例,其中的值是从数据类中带有参数的函数求值的?

到目前为止,这就是我所在的位置:

@dataclass
class Person: 
    def Name(self):
        return f'My name is {self.name[0]} {self.name[1]}.'

    def Age(self):
        return f'I am {self.age} years old.'

    name: field(default_factory=Name(self), init=True)
    age: field(default_factory=Age(self), init=True)

person = Person(('John', 'Smith'), '100')
print(person)
Run Code Online (Sandbox Code Playgroud)

电流输出:

@dataclass
class Person: 
    def Name(self):
        return f'My name is {self.name[0]} {self.name[1]}.'

    def Age(self):
        return f'I am {self.age} years old.'

    name: field(default_factory=Name(self), init=True)
    age: field(default_factory=Age(self), init=True)

person = Person(('John', 'Smith'), '100')
print(person)
Run Code Online (Sandbox Code Playgroud)

这是我想要实现的输出:

Person(name=('John', 'Smith'), age='100')
Run Code Online (Sandbox Code Playgroud)

我试图使用如何在数据类字段中引用“self”?供有关此主题的参考。

python self python-3.x python-dataclasses

4
推荐指数
1
解决办法
6136
查看次数

为什么`dataclasses.asdict(obj)`&gt;比`obj .__ dict __()`慢10倍

我正在使用Python 3.6和ericvsmithdataclassesbackport软件包。

看来通话dataclasses.asdict(my_dataclass)比通话慢约10倍my_dataclass.__dict__

In [172]: @dataclass
     ...: class MyDataClass:
     ...:     a: int
     ...:     b: int
     ...:     c: str
     ...: 

In [173]: %%time
     ...: _ = [MyDataClass(1, 2, "A" * 1000).__dict__ for _ in range(1_000_000)]
     ...: 
CPU times: user 631 ms, sys: 249 ms, total: 880 ms
Wall time: 880 ms

In [175]: %%time
     ...: _ = [dataclasses.asdict(MyDataClass(1, 2, "A" * 1000)) for _ in range(1_000_000)]
     ...: 
CPU times: user 11.3 s, sys: …
Run Code Online (Sandbox Code Playgroud)

python python-dataclasses

3
推荐指数
1
解决办法
1492
查看次数

如何使用数据类生成字段值?

我有以下课程:

class WordItem:
    def __init__(self, phrase: str, word_type: WORD_TYPE):
        self.id = f'{phrase}_{word_type.name.lower()}'
        self.phrase = phrase
        self.word_type = word_type
        @classmethod

    def from_payload(cls, payload: Dict[str, Any]) -> 'WordItem':
        return cls(**payload)
Run Code Online (Sandbox Code Playgroud)

如何将此类重写为数据类

具体来说,如何id宣布该领域?它具有生成的值,而不是代码创建实例将提供的字段.

python python-3.7 python-dataclasses

3
推荐指数
1
解决办法
320
查看次数

Python 数据类,验证初始化参数的 Pythonic 方法是什么?

在没有覆盖内置 init 的数据类的情况下,在实例化之前验证 init 参数的 Pythonic 方法是什么?

我想也许利用__new__dunder 方法是合适的?

from dataclasses import dataclass

@dataclass
class MyClass:
    is_good: bool = False
    is_bad: bool = False

    def __new__(cls, *args, **kwargs):
        instance: cls = super(MyClass, cls).__new__(cls, *args, **kwargs)
        if instance.is_good:
            assert not instance.is_bad
        return instance
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

3
推荐指数
2
解决办法
2878
查看次数

Python 数据类:模拟冻结数据类中的默认工厂

我试图在我的单元测试中使用 freezegun 来修补数据类中的字段,该字段设置为对象初始化时的当前日期。我想这个问题与任何修补被用作 default_factory 的函数的尝试有关,只是在 freezegun 之外。数据类被冻结,所以它是不可变的。

例如,如果我的数据类是:

@dataclass(frozen=True)
class MyClass:
    name: str
    timestamp: datetime.datetime = field(init=False, default_factory=datetime.datetime.now)
Run Code Online (Sandbox Code Playgroud)

当我使用 freezegun 修补 datetime 时,它​​对 MyClass 中时间戳的初始化没有影响(它仍然将时间戳设置为单元测试中 now() 返回的当前日期,导致测试失败)。

我假设它与在补丁到位之前加载的默认工厂和模块有关。我尝试修补日期时间,然后使用 importlib.reload 重新加载模块,但没有运气。

我目前的解决方案是:

@dataclass(frozen=True)
class MyClass:
    name: str
    timestamp: datetime.datetime = field(init=False)

def __post_init__(self):
   object.__setattr__(self, "timestamp", datetime.datetime.now())
Run Code Online (Sandbox Code Playgroud)

哪个有效。

理想情况下,我想要一个非侵入性的解决方案,它不需要我更改我的生产代码来启用我的单元测试。

python unit-testing patch freezegun python-dataclasses

3
推荐指数
1
解决办法
2172
查看次数