[英]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.