【问题标题】:Setting a function with a parser command使用解析器命令设置函数
【发布时间】:2022-01-08 00:48:40
【问题描述】:

当我启动我的代码时,我想选择一个将要使用的函数(从一组函数中)。不幸的是,我有很多循环并且代码非常昂贵,因此以下伪代码已被高度弃用:

import argparse
import mystuff


code body in which my_variable gets created

if args.my_index == 1:
  def my_func(my_variable):
    return my_variable + 1

if args.my_index == 2:
  def my_func(my_variable):
    return my_variable**2 +1

使用过以下命令:

$ python3 my_code.py --index 1

我正在考虑将函数提升为外部类模块,可能使用类初始化的属性。

【问题讨论】:

    标签: python python-3.x argparse


    【解决方案1】:

    您可以像元组一样在容器中注册您的函数。然后您可以通过索引检索它们。 ArgumentParser 对象的 .index 属性将比元组索引多 1:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--index', type=int)
    args = parser.parse_args()
    
    my_variable = 10
    funcs = (lambda x: x + 1, lambda x: x ** 2 + 1, lambda x: x ** 3 + 1)
    
    if args.index is not None:
        print(funcs[args.index - 1](my_variable))
    

    这样当你使用python3 my_code.py --index 1执行你的脚本时,.index是1,所以你需要得到元组的第一项是args.index - 1

    输出:11

    如果您的函数遵循特定模式(如my_variable ** n + 1 此处),您可以定义一个通用函数来处理它而无需注册所有函数:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--index', type=int)
    args = parser.parse_args()
    
    my_variable = 10
    
    def func(x):
        return my_variable ** x + 1
    
    if args.index is not None:
        print(func(args.index))
    

    【讨论】:

    • lambda 函数是一种结构函数,因为您将指针指向“表达式”
    【解决方案2】:

    这是一个示例,您可以如何使用带有函数的基类作为从它继承的类来自动构建命令行(使用基类上的 __subclasses__() 方法)并进行计算,而无需编写一些荒谬的 if 序列声明。

    有关子类的更多信息,请参阅 Python 文档中的 here

    import argparse
    
    # base class for all your functions to inherit from    
    class mystuff():
            pass
    
    # function classes inherit from mystuff, provide at least a docstring and a calculate() method.            
    class fun1(mystuff):
        '''
        Calculate fun1
        '''
        def calculate(self,value):
            return value*2
        
    class fun2(mystuff):
        '''
        Calculate fun2
        '''
        def calculate(self,value):
            return value*23
    
    if __name__=="__main__":
        parser = argparse.ArgumentParser(description="Allow calling functions each defined in their own class")
    
        # find all the classes to be used as commandline arguments
        for fun in mystuff.__subclasses__():
    #        print( f"Creating argument for {fun.__name__}" )
            parser.add_argument( f'--{fun.__name__}', default=0, dest='function', action='store_const', const=fun, help=fun.__doc__)
        parser.add_argument('variable', type=int, help="Value to pass to calculation")
        
        args = parser.parse_args()
    
        # create an instance and call its calculate function passing the variable value
        result = args.function().calculate(args.variable)
        
        print( f"Calling {args.function.__name__} with variable {args.variable} gives result {result}" )
    
        
    

    了解用法:

    fun1.py -h
    

    给予:

    usage: fun1.py [-h] [--fun1] [--fun2] variable
    
    Allow calling functions each defined in their own class
    
    positional arguments:
      variable    Value to pass to calculation
    
    optional arguments:
      -h, --help  show this help message and exit
      --fun1      Calculate fun1
      --fun2      Calculate fun2
    

    调用其中一个函数:

    fun1.py --fun1 235
    

    给出结果:

    Calling fun1 with variable 235 gives result 470
    

    我确信这可以变得更复杂,也许可以通过使用子解析器消除每个函数名称前的 -- 的需要。

    【讨论】:

    • 恕我直言,Sorus 提出的解决方案更简洁。无论如何,你的建议对我和其他许多人来说都是非常有教育意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多