标签: python-dataclasses

Python中定义一个数据类的正确方法是什么,该数据类同时具有自动生成的 __init__ 和来自值字典的附加 init2

在 Python 中,我有一个包含十多个成员的数据类。我用它创建一个字典并将其发布到 ElasticSearch 中

现在我想从 ElasticSearch获取一个字典并用它来初始化数据类。

自从:

  1. Python 不允许创建具有不同签名的第二个 __ init __ 。
  2. 我不想手动编写自动生成的 __ init __ 只是为了添加可选参数
  3. 我不想添加可选参数来接受字典,只是为了让 __ init __ 保持自动生成。

我想添加第二个方法init2,它将返回数据类的实例,并将传递的 dict 参数解析到自动生成的 __ init __ 方法中。


我会感谢您的意见来决定我下面建议的解决方案是否是正确的实施。

另外,这种实现可以被视为一种工厂吗?

谢谢。


跟进:由于我从 ES 请求中获取的 JSON\dictionary 是:

  1. 与数据类具有完全相同的关键字

  2. 是扁平的,id,没有嵌套对象。

我可以简单地将这些值作为 **dict 传递到自动生成的 __ init __ 方法中。

对于这个具体案例,请参阅下面我的回答:


from dataclasses import dataclass

@dataclass
class MyData:
    name: str
    age: int = 17

    @classmethod
    def init_from_dict(cls, values_in_dict: dict):
        # Original line using MyData was fixed …
Run Code Online (Sandbox Code Playgroud)

python data-class python-dataclasses

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

定义一个行为类似于打字的自定义类型。Any

我需要创建一个类型,其行为类似于typing.Any类型检查器(mypy)查看时的行为,但与typing.Any.

用例是一些漂亮的“元”代码,需要从一组可以用 注释的其他变量中找到用此类型注释的变量typing.Any。请注意,我永远不需要实际创建此类型的实例,我只需要它在数据类上下文中进行类型注释。例子:

from dataclasses import dataclass, fields
from typing import Any


MyAny = ... # What to put here?

@dataclass()
class Test:

    a: Any
    b: MyAny = None


for field in fields(Test):
    if field.type == MyAny:
        print(f"It's {field.name}")   # This should print "It's b"
Run Code Online (Sandbox Code Playgroud)

我尝试过的事情:

  1. 不起作用,因为你不能继承 Any:TypeError: Cannot subclass <class 'typing._SpecialForm'>

    class MyAny(Any):
       pass
    
    Run Code Online (Sandbox Code Playgroud)
  2. 不起作用,因为它与正常的 Any 没有区别(上面代码片段的结果是It's a\nIt's b

    MyAny = Any
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在运行时工作,但 mypy 抱怨默认值: Mypy: Incompatible types in assignment …

python types type-hinting mypy python-dataclasses

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

DataClass 是否适合替换字典?

我在代码中经常使用字典作为数据结构。而不是Tuple像 Python 允许的那样返回几个值:

def do_smth():
  [...]
  return val1, val2, val3
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用具有命名键优势的字典。但是对于复杂的嵌套字典,很难在其中导航。几年前我用 JS 编码时,我也喜欢字典,因为我可以像调用子部分一样thing.stuff.foo,IDE 帮助我处理结构。

我刚刚发现了DataClasspython 中的新内容,除了替换字典之外,我不确定这是什么原因?对于我所阅读的内容,DataClass内部无法包含函数,并且其参数的初始化已简化。

我想对此发表评论,你如何使用DataClass, 或关于 python 中的字典。

python dictionary python-dataclasses

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

在 Python 中使用数据类方法定义属性

我有一个用于边界框坐标的类,我想将其转换为数据类,但我无法弄清楚如何像在普通类中那样使用类方法设置属性。这是正常的类:

class BBoxCoords:
    """Class for bounding box coordinates"""
    def __init__(self, top_left_x: float, top_left_y: float, bottom_right_x: float, bottom_right_y: float):
        self.top_left_x = top_left_x
        self.top_left_y = top_left_y
        self.bottom_right_x = bottom_right_x
        self.bottom_right_y = bottom_right_y
        self.height = self.get_height()

    def get_height(self) -> float:
        return self.bottom_right_y - self.top_left_y
Run Code Online (Sandbox Code Playgroud)

这就是我想要它做的事情:

bb = BBoxCoords(1, 1, 5, 5)
bb.height
> 4
Run Code Online (Sandbox Code Playgroud)

这正是我想要的。我尝试用数据类做同样的事情

from dataclasses import dataclass    

@dataclass
class BBoxCoords:
    """Class for bounding box coordinates"""
top_left_x: float
top_left_y: float
bottom_right_x: float
bottom_right_y: float
height = self.get_height()

def get_height(self) -> float:
    return …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-dataclasses

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

在 Django 模型中使用 Python 数据类

我的目标是在 Django PostgreSQL 中创建一个类似结构体的对象,例如:

specs.coordinate.x
specs.coordinate.y
specs.coordinate.z
Run Code Online (Sandbox Code Playgroud)

因此xyz应该是坐标的子类。它们也应该是可变的,因此不能使用命名元组。

我已经尝试使用新的数据类:

from django.db import models
from dataclasses import dataclass

class Specs(models.Model):
    name = models.CharField(max_length=80)
    age = models.IntegerField()

    @dataclass
    class coordinate:
        x: float
        y: float
        z: float
Run Code Online (Sandbox Code Playgroud)

然而,坐标 x,y,z项在 pgAdmin 中不可见:

在此输入图像描述

我究竟做错了什么?有没有比数据类更好的方法?

python django postgresql django-models python-dataclasses

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

napoleon 和 autodoc 如何交互记录成员

我注意到 Sphinx 呈现类描述的行为发生了变化。鉴于此代码

# my example happens to be a dataclass, but the behavior for 
# regular classes is the same
@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.
    """
    var_int: int
    var_str: str
Run Code Online (Sandbox Code Playgroud)

加上一些通用的狮身人面像设置,我大约两年前就得到了这个

文档仅显示文档字符串

现在我得到了这个

文档显示类变量,就像它们在文档字符串中一样

有没有办法告诉 Sphinx 不要将类变量添加到类定义的底部?尤其令人烦恼的是,它假设它们的值为None,只是因为它们没有默认值。


这个问题是在这篇文章的讨论中出现的,其中还包含有关 Sphinx 配置等的评论中的更多上下文。

python python-sphinx autodoc sphinx-napoleon python-dataclasses

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

自定义数据类 asdict 键名

如何创建具有自定义字典表示形式的数据类?

字典输出示例:

{
    '$1': 'foo',
    '$2': 'bar',
    '$3': 'baz'
}
Run Code Online (Sandbox Code Playgroud)

显然我不能有数据类

@dataclass
class Foo:
    $1: str
    ...
Run Code Online (Sandbox Code Playgroud)

我需要它表示为

@dataclass
class Foo:
    one: str
    ...
Run Code Online (Sandbox Code Playgroud)

例如,但我想dataclasses.asdict(foo)返回“$1”等键名。

如果

x = {
    '$1': 'foo',
    '$2': 'bar',
    '$3': 'baz'
}
foo = Foo(**x)
assert foo.one == 'foo'
assert foo.two == 'bar'
assert foo.three == 'baz'
Run Code Online (Sandbox Code Playgroud)

工作过

python python-3.x python-dataclasses

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

将 Python 类转换为 Numpy 数组

我可以将 python 类转换为 numpy 吗array

from dataclasses import dataclass
import numpy as np
@dataclass
class X:
    x: float = 0
    y: float = 0
x = X()
x_array = np.array(x) # would like to get an numpy array np.array([X.x,X.y])
Run Code Online (Sandbox Code Playgroud)

在最后一步中,我想获得一个数组np.array([X.x, X.y])。相反,我得到了array(X(x=0, y=0), dtype=object)

我可以提供 的方法,dataclass以便根据需要进行转换(或重载 的现有方法之一dataclass)吗?

python numpy python-3.x python-dataclasses

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

嵌套数据类到 dict

我有很多使用post_init嵌套的数据类

from dataclasses import dataclass
from typing import List
from typing import Optional
from typing import Union


@dataclass
class MyClass:
    signed_key: str
    signature: str


@dataclass
class Message:
    signature: str
    my_class: Union[MyClass, dict]
    protocol_version: str
    signed_message: str

    def __post_init__(self):
        self.my_class = MyClass(**self.my_class)
Run Code Online (Sandbox Code Playgroud)

它工作得很好,但问题是,如果我想将 Message 转换为 dict,如下所示:

#create a message object before
print(message.__dict__)
Run Code Online (Sandbox Code Playgroud)

我得到的输出:

{'signature': 'test', 'my_class': Myclass(signed_key='test', signature='test'), 'protocol_version': 'test', 'signed_message': 'test'}
Run Code Online (Sandbox Code Playgroud)

我想要什么(嵌套字典):

{'signature': 'test', 'my_class': {'signed_key': 'test', 'signature': 'test'}, 'protocol_version': 'test', 'signed_message': 'test'}
Run Code Online (Sandbox Code Playgroud)

我可以使用像 attrs 或 pydantic 这样的库,但这里的目标是只使用纯 python

python python-dataclasses

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

如何测试可以使用环境变量初始化的数据类?

我有以下数据类:

import os
import dataclasses

@dataclasses.dataclass
class Example:
    host: str = os.environ.get('SERVICE_HOST', 'localhost')
    port: str = os.environ.get('SERVICE_PORT', 30650)
Run Code Online (Sandbox Code Playgroud)

我该如何为此编写测试?我尝试了以下看起来应该有效的方法:

from stackoverflow import Example
import os


def test_example(monkeypatch):
    # GIVEN environment variables are set for host and port
    monkeypatch.setenv('SERVICE_HOST', 'server.example.com')
    monkeypatch.setenv('SERVICE_PORT', '12345')
    #   AND a class instance is initialized without specifying a host or port
    example = Example()
    # THEN the instance should reflect the host and port specified in the environment variables
    assert example.host == 'server.example.com'
    assert example.port == '12345' …
Run Code Online (Sandbox Code Playgroud)

python environment-variables pytest python-3.x python-dataclasses

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