匹配多种可能的类型?

发布于 2025-01-29 21:55:56 字数 1773 浏览 7 评论 0原文

由于我强大的弱打字编程背景,我对生锈和挣扎的生锈非常新。

下面的代码应通过PYO3将收到的数据写入XLSX工作表中。我只是不知道如何处理上一场比赛,因为“值”是pyany类型(这是其方法提取物可以输出多种类型,例如字符串,F32等。我想要特定的行为,具体取决于提取类型)。

也许我只能为每种潜在提取类型的链匹配(如果第一次输出ERR,请尝试下一个),但我怀疑可能会有更好的方法。也许我只是通过错误的设计来解决问题。任何见解都将受到欢迎。

pub trait WriteValue {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError>;
}

impl WriteValue for String {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError> {
        worksheet.write_string(row, col, &self, format)
    }
}

impl WriteValue for f32 {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError> {
        worksheet.write_number(row, col, f64::from(*self), format)
    }
}

fn _write(path: &str, data: HashMap<u32, &PyList>, _highlight: Option<&PyDict>) -> Result<(), XlsxError> {
    let workbook = Workbook::new(path);
    let mut worksheet = workbook.add_worksheet(None)?;

    let format_bold = workbook.add_format().set_bold();

    for (row_index, values) in data {

        let mut col_idx: u16 = 0;

        for value in values {
            col_idx += 1;
            let row_format= match &row_index {
                0 => Some(&format_bold),
                _ => None
                };
            match value.extract::<String>() {
                Ok(x) => x.write_value(&mut worksheet, row_index.clone(), &col_idx -1, row_format)?,
                Err(_) => { }
                }
        }
    }
    workbook.close()
    }

I'm very, very new to Rust and struggling with it because of my strong weakly typed programming background.

The code below should write data being received from Python via PYO3 into a XLSX worksheet. I just don't know how to handle the last match, because "value" is of type PyAny (this is, its method extract can output multiple types such as String, f32, etc. and I want a specific behavior depending on the extracted type).

Maybe I could just chain matches for each potential extracted type (if first outputs Err, try the next), but I suspect there could be a better way. Maybe I'm just approaching the problem with a wrong design. Any insights will be welcome.

pub trait WriteValue {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError>;
}

impl WriteValue for String {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError> {
        worksheet.write_string(row, col, &self, format)
    }
}

impl WriteValue for f32 {
    fn write_value(&self, worksheet: &mut Worksheet, row: u32, col: u16, format: Option<&Format>) -> Result<(), XlsxError> {
        worksheet.write_number(row, col, f64::from(*self), format)
    }
}

fn _write(path: &str, data: HashMap<u32, &PyList>, _highlight: Option<&PyDict>) -> Result<(), XlsxError> {
    let workbook = Workbook::new(path);
    let mut worksheet = workbook.add_worksheet(None)?;

    let format_bold = workbook.add_format().set_bold();

    for (row_index, values) in data {

        let mut col_idx: u16 = 0;

        for value in values {
            col_idx += 1;
            let row_format= match &row_index {
                0 => Some(&format_bold),
                _ => None
                };
            match value.extract::<String>() {
                Ok(x) => x.write_value(&mut worksheet, row_index.clone(), &col_idx -1, row_format)?,
                Err(_) => { }
                }
        }
    }
    workbook.close()
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绿萝 2025-02-05 21:55:56

这主要是PYO3 API问题,尽管我对此并不非常熟悉,但我认为PYO3没有内置的“ MultieXtract”,所以它可能。

但是,首先,由于您不关心err条款,您可以通过简单地链接语句简单地简化代码,它们是句法糖,但对于单一或二进制布尔值conditions they're really convenient eg

if let Ok(x) = value.extract::<String>() {
    x.write_value(...)
} else if let Ok(x) = value.extract::<f32>() {
    // handle this case and possibly add a bunch more
} else {
    // handle no case matching (optional if should be ignored)
}

Second, it looks like pyo3 lets you

#[derive(FromPyObject)]
enum Writables {
    #[pyo3(transparent, annotation = "str")]
    String(String),
    #[pyo3(transparent, annotation = "float")]
    Float(f32),
    // put the other cases here
}

然后您可以extract to 并立即匹配所有变体(并分别处理“不支持类型”)。

实际上,在这一点上,该特征可能不必要,除非它用于其他内容,否则您可以直接在枚举上将write_value方法直接使用。

旁注:将python float(是双重)提取到f32,然后立即将其扩展到f64以将其写出似乎...奇怪。为什么不首先提取f64

This is mostly a pyo3 API issue, and I don't think pyo3 has built-in "multiextract" though I'm not ultra familiar with it, so it may.

However, first since you don't care about the Err clause you could simplify your code by simply chaining if let statements, they're syntactic sugar but for unary or binary boolean conditions they're really convenient e.g.

if let Ok(x) = value.extract::<String>() {
    x.write_value(...)
} else if let Ok(x) = value.extract::<f32>() {
    // handle this case and possibly add a bunch more
} else {
    // handle no case matching (optional if should be ignored)
}

Second, it looks like pyo3 lets you derive enums, since WriteValue is apparently an internal trait it would make sense to derive the corresponding enum:

#[derive(FromPyObject)]
enum Writables {
    #[pyo3(transparent, annotation = "str")]
    String(String),
    #[pyo3(transparent, annotation = "float")]
    Float(f32),
    // put the other cases here
}

then you can extract to that and match all the variants at once (and handle the "unsupported types" separately).

In fact at this point the trait is probably unecessary, unless it's used for other stuff, you could just have your write_value method on the enum directly.

side-note: extracting a python float (which is a double) to an f32 then immediately widening it to an f64 in order to write it out seems... odd. Why not extract an f64 in the first place?

离去的眼神 2025-02-05 21:55:56

Pyany可以尝试降低 到任何其他 。我不熟练熟练pyo3,但是我在这里看到的唯一方法是尝试降低您支持的类型,否则也许会启动错误:

fn _write(path: &str, data: HashMap<u32, &PyList>, _highlight: Option<&PyDict>) -> Result<(), XlsxError> {
    let workbook = Workbook::new(path);
    let mut worksheet = workbook.add_worksheet(None)?;

    let format_bold = workbook.add_format().set_bold();

    for (row_index, values) in data {

        let mut col_idx: u16 = 0;

        for value in values {
            col_idx += 1;
            let row_format= match &row_index {
                0 => Some(&format_bold),
                _ => None
            };
            if let Ok(string) = value.downcast::<PyString> {
                // handle pystring object
                string.write_value(&mut worksheet, row_index.clone(), &col_idx -1, row_format)?;
                ...
            } else if let Ok(int) = value.downcast::<PyInt> {
                // handle pyint object
                ...
            } else {
                // error, or not supported
            }
        }
    }
    workbook.close()
}

PyAny can be try to downcast to any other Python type. I am not proficient with PyO3, but the only approach I see here is to try to downcast to the types you support otherwise maybe launch an error:

fn _write(path: &str, data: HashMap<u32, &PyList>, _highlight: Option<&PyDict>) -> Result<(), XlsxError> {
    let workbook = Workbook::new(path);
    let mut worksheet = workbook.add_worksheet(None)?;

    let format_bold = workbook.add_format().set_bold();

    for (row_index, values) in data {

        let mut col_idx: u16 = 0;

        for value in values {
            col_idx += 1;
            let row_format= match &row_index {
                0 => Some(&format_bold),
                _ => None
            };
            if let Ok(string) = value.downcast::<PyString> {
                // handle pystring object
                string.write_value(&mut worksheet, row_index.clone(), &col_idx -1, row_format)?;
                ...
            } else if let Ok(int) = value.downcast::<PyInt> {
                // handle pyint object
                ...
            } else {
                // error, or not supported
            }
        }
    }
    workbook.close()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文