繁体   English   中英

当属性不遵守命名规则时python中的数据类

[英]Dataclass in python when the attribute doesn't respect naming rules

如果您有这样的数据(来自 yaml 文件):

items:
  C>A/G>T: "#string"
  C>G/G>C: "#string"
  ...

如何将其加载到明确说明其键和类型的数据类中? 理想情况下,我会:

@dataclasses.dataclass
class X:
    C>A/G>T: str
    C>G/G>C: str
...

更新:

SBS_Mutations = TypedDict(
    "SBS_Mutations",
    {
        "C>A/G>T": str,
        "C>G/G>C": str,
        "C>T/G>A": str,
        "T>A/A>T": str,
        "T>C/A>G": str,
        "T>G/A>C": str,
    },
)

my_data = {....}

SBS_Mutations(my_data) # not sure how to use it here

如果您想要这样的符号,它们显然不能是 Python 标识符,然后,想要使用具有属性访问权限的数据类为您提供的设施是没有意义的。

只需将您的数据保存在字典或 Pandas 数据框中,这些名称可以是列标题。

否则,发布一个适当的代码片段,其中包含您从何处获取数据的最小示例,然后,可以添加一个答案,一个将您的原始名称转换为有效 Python 属性名称的适当位置,并帮助构建一个动态的数据类。

这听起来像是我最近发布的dotwiz库的一个很好的用例。 这提供了一个dict子类,它为嵌套键启用属性样式点访问。

在最近的版本中,它提供了一个DotWizPlus实现(一个dict对象的包装器),它还对键进行大小写转换,以便它们是有效的小写 Python 标识符名称,如下所示。

# requires the following dependencies:
#   pip install PyYAML dotwiz
import yaml
from dotwiz import DotWizPlus

yaml_str = """
items:
  C>A/G>T: "#string"
  C>G/G>C: "#string"
"""

yaml_dict = yaml.safe_load(yaml_str)
print(yaml_dict)

dw = DotWizPlus(yaml_dict)
print(dw)

assert dw.items.c_a_g_t == '#string'  # True

print(dw.to_attr_dict())

输出:

{'items': {'C>A/G>T': '#string', 'C>G/G>C': '#string'}}
✪(items=✪(c_a_g_t='#string', c_g_g_c='#string'))
{'items': {'c_a_g_t': '#string', 'c_g_g_c': '#string'}}

注意:目前DotWiz实例访问键items时会失败,因为键名与内置属性dict.items()冲突。 我目前已经提交了一个错误请求,并希望特别能解决这个边缘案例。

类型提示

如果您想要字段名称的类型提示或自动建议,您可以尝试这样的方法,您可以从DotWizPlus子类化:

import yaml
from dotwiz import DotWizPlus


class Item(DotWizPlus):
    c_a_g_t: str
    c_g_g_c: str

    @classmethod
    def from_yaml(cls, yaml_string: str, loader=yaml.safe_load):
        yaml_dict = loader(yaml_str)
        return cls(yaml_dict['items'])


yaml_str = """
items:
  C>A/G>T: "#string1"
  C>G/G>C: "#string2"
"""

dw = Item.from_yaml(yaml_str)
print(dw)
# ✪(c_a_g_t='#string1', c_g_g_c='#string2')

assert dw.c_a_g_t == '#string1'  # True

# auto-completion will work, as IDE knows the type is a `str`
# dw.c_a_g_t.

数据类

如果您仍然希望将数据类用于类型提示,您还可以查看另一个名为dataclass-wizard 的库,它也可以帮助简化此任务。

更具体地说, YAMLWizard使使用 YAML 加载/转储类对象变得更加容易。 请注意,默认情况下,这会在后台使用PyYAML库。

请注意,在这种情况下,我无法让 case-transform 工作,因为我猜这是底层to_snake_case()实现中的一个错误。 我还将提交一个错误请求来调查这个边缘案例。 但是,现在如果更明确地指定 YAML 中的键名,它应该可以工作:

from dataclasses import dataclass

from dataclass_wizard import YAMLWizard, json_field

yaml_str = """
items:
  C>A/G>T: "#string"
  C>G/G>C: "#string"
"""


@dataclass
class Container(YAMLWizard):
    items: 'Item'


@dataclass
class Item:
    c_a_g_t: str = json_field('C>A/G>T')
    c_g_g_c: str = json_field('C>G/G>C')


c = Container.from_yaml(yaml_str)
print(c)

# True
assert c.items.c_g_g_c == c.items.c_a_g_t == '#string'

输出:

Container(items=Item(c_a_g_t='#string', c_g_g_c='#string'))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM