【问题标题】:Unable to call variable defined in dataclass无法调用数据类中定义的变量
【发布时间】:2022-01-06 08:17:37
【问题描述】:

我有一个数据类如下:

from dataclasses import dataclass, field
from typing import Any, Dict

raw_dir = r"C:..." # path of the raw dir
processed_dir = r"C:..." # path of the processed dir

@dataclass
class Files:
    raw_path: Path = Path(raw_dir)
    processed_path: Path = Path(processed_dir)

    path_dict: Dict[str, Any] = field(
        default_factory=lambda: {
            "raw_train_file": Path(raw_path, "raw_train.csv"),
            "processed_train_file": Path(processed_path, "processed_train.csv"),
        }
    )
Files().path_dict

这将引发错误name "raw_path" is not defined. 但是当您尝试在第一行之后立即打印raw_path 时,它可以完成,因此问题可能来自path_dict。我尝试将键值对替换为 "raw": Path(directory) 并且它有效,所以我认为这不是数据类型的问题。


上下文:我将dataclass 视为config 文件(func),这样当我需要调用默认路径时,我可以使用:

pd.read_csv(Files().path_dict["raw_train_file"])

【问题讨论】:

  • 你在哪里定义了directory?你做了什么进口?
  • 导入未添加到帖子中。
  • 又是后期绑定,试试lambda r=raw_file: {"raw": r}
  • @jonrsharpe 谢谢,它成功了,我在这里阅读后期绑定:docs.python-guide.org/writing/gotchas
  • 你真的会在那里使用 non-default 值吗?无论如何,属性可能更合适。

标签: python python-dataclasses


【解决方案1】:

您的问题是 default_factory 必须是一个零参数的可调用对象。因此,它不能使用任何成员变量。在这里,由于成员变量的初始化很简单,你可以重复初始化,只使用全局变量:

...
path_dict: Dict[str, Any] = field(
    default_factory=lambda: {
        "raw_train_file": Path(Path(raw_dir), "raw_train.csv"),
        "processed_train_file": Path(Path(processed_dir), "processed_train.csv"),
    }

但您也可以使用特殊的__post_init__ 方法,该方法在其他初始化后由生成的__init__ 调用。当它接收到self 参数时,它可以使用成员变量:

@dataclass
class Files:
    raw_path: Path = Path(raw_dir)
    processed_path: Path = Path(processed_dir)

    def __post_init__(self):
        self.path_dict: Dict[str, Any] = {
            "raw_train_file": Path(self.raw_path, "raw_train.csv"),
            "processed_train_file": Path(self.processed_path, "processed_train.csv"),
        }

【讨论】:

    【解决方案2】:

    另一种选择是使用functools.cached_property 来避免需要在数据类中定义__post_init__ 方法。请注意,我并不认为这是一个“更好”的解决方案,只是它是实现相同目标的另一种方式。

    from dataclasses import dataclass
    from functools import cached_property
    from pathlib import Path
    from typing import Any, Dict
    
    raw_dir = r"C:..."  # path of the raw dir
    processed_dir = r"C:..."  # path of the processed dir
    
    
    @dataclass
    class Files:
        raw_path: Path = Path(raw_dir)
        processed_path: Path = Path(processed_dir)
    
        @cached_property
        def path_dict(self) -> Dict[str, Any]:
            return {
                "raw_train_file": Path(self.raw_path, "raw_train.csv"),
                "processed_train_file": Path(self.processed_path, "processed_train.csv"),
            }
    
    
    print(Files().path_dict)
    

    输出:

    {'raw_train_file': PosixPath('C:.../raw_train.csv'), 'processed_train_file': PosixPath('C:.../processed_train.csv')}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-28
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 2020-01-16
      • 1970-01-01
      • 2015-05-01
      • 2013-12-21
      相关资源
      最近更新 更多