【问题标题】:What is the best way to save and recall a sequence of functions and arguments保存和调用一系列函数和参数的最佳方法是什么
【发布时间】:2021-06-10 08:15:43
【问题描述】:

在 Python 3.8.8 中,我正在寻找一种方法来保存和调用一系列函数和相关参数。我遇到了看起来像这样做的好方法的数据类,但无法检索函数名称或参数。我什至不确定数据类是否可以实现我想要做的事情。

from dataclasses import dataclass
from dataclass_csv import DataclassWriter, DataclassReader

def foo(bar):
    print(bar)
    return True
   
@dataclass
class Step:
    name: str
    fn: any
    args: any = None

steps = [ Step(name ='step 1', fn=foo, args=('bar 1',)),
          Step(name ='step 2', fn=foo, args=('bar 2',)) ]

with open('steps.csv', "w") as f:
    w = DataclassWriter(f, steps, Step)
    w.write()
 
with open("steps.csv") as f:
    reader = DataclassReader(f, Step)
    rsteps  = [row for row in reader]
    print(rsteps)

steps.csv 包含预期值。

name,fn,args
step 1,<function foo at 0x0000019E3A12EE50>,"('bar 1',)"
step 2,<function foo at 0x0000019E3A12EE50>,"('bar 2',)"

但当回读时,rsteps 会以布尔值结束 fnarg

[Step(name='step 1', fn=True, args=True), Step(name='step 2', fn=True, args=True)]

我将fnarg 类型定义为any,因为我找不到任何可以在那里工作的类型。我试过Callable[...,bool] (from typing import Callable) 但得到了一个TypeError: 'type' object is not subscriptable

【问题讨论】:

    标签: python python-3.x csv


    【解决方案1】:

    anybuiltin funtion
    typing.Anytyping library 中可用的类型提示。
    所以千万不要使用any作为类型提示,因为它是一个函数,而不是一个类型。

    您的foo 函数接受一个字符串并返回一个布尔值,因此它的类型是typing.Callable[[str], bool]

    有了这两个修改,我们还是写了同样的东西:

    import typing
    from dataclasses import dataclass
    from dataclass_csv import DataclassWriter, DataclassReader
    
    
    def foo(bar):
        print(bar)
        return True
    
    
    @dataclass
    class Step:
        name: str
        fn: typing.Callable[[str], bool]
        args: typing.Any = None
    
    
    steps = [
        Step(name='step 1', fn=foo, args=('bar 1',)),
        Step(name='step 2', fn=foo, args=('bar 2',))
    ]
    
    with open('steps.csv', "w") as f:
        w = DataclassWriter(f, steps, Step)
        w.write()
    
    # with open("steps.csv") as f:
    #     reader = DataclassReader(f, Step)
    #     rsteps = [row for row in reader]
    #     print(rsteps)
    

    但是 CSV 文件内容无法读回,我们得到一个错误:TypeError: Type Callable cannot be instantiated; use a non-abstract subclass instead 因为它无法从写入的内容中读回函数(例如&lt;function foo at 0x000001EF2A232F28&gt;)。

    Python 函数不能以这种方式(反)序列化。数据类可以方便地存储数据,但如果没有严重的黑客攻击,它们就无法存储函数。

    你可以marshall你的函数,看看这个其他问题:Is there an easy way to pickle a python function (or otherwise serialize its code)?

    【讨论】:

      【解决方案2】:

      我使用 lambda 想出了这个。它相当简单,也允许任意参数。

      from dataclasses import dataclass
      from dataclass_csv import DataclassWriter, DataclassReader
      
      def foo(bar,i):
          print(f'foo {bar} {i}')
          return True
      
      @dataclass
      class Step:
          name: str
          fn: str
      
      steps = [ Step(name ='step 1', fn="foo('bar1', 1)"),
                Step(name ='step 2', fn="foo('bar2', 2)")]
      
      with open('steps.csv', "w") as f:
          w = DataclassWriter(f, steps, Step)
          w.write()
          
      reader = None 
      with open("steps.csv") as f:
          reader = DataclassReader(f, Step)
          rsteps  = [row for row in reader]
          print(rsteps)
      
      s=rsteps[0]
      rfn = eval(f'lambda: {s.fn}')
      rfn()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-19
        • 2021-03-28
        • 1970-01-01
        • 2015-09-15
        • 2011-07-23
        • 1970-01-01
        • 2018-06-16
        • 1970-01-01
        相关资源
        最近更新 更多