【问题标题】:Recursive calculator with adding and substracting带加法和减法的递归计算器
【发布时间】:2021-12-30 01:31:39
【问题描述】:

我制作了一个带有 3 个单独参数的嵌套函数 - 每个函数都带有一个:(arg1)(operation)(arg2)

def simple_functional_calc(arg1: int):
    def inner_functional_calc(operation: str):
        import operator
        ops = {
            '+': operator.add,
            '-': operator.sub
        }

        def inner_inner_functional_calc(arg2: int):
            return ops[operation](arg1, arg2)
        return inner_inner_functional_calc
    return inner_functional_calc

还有其他想法(没有导入):

def calculator(arg1: int):
    def inner_calc(operation: str):
        def add(arg2: int):
            return arg1 + arg2

        def sub(arg2: int):
            return arg1 - arg2

        if operation == '+':
            return add
        elif operation == '-':
            return sub
    return inner_calc

在此示例中,print(calculator(1)('+')(7)) 的结果为 8。问题是使函数可以接受任意数量的参数并在最后一个参数为“=”时返回结果。示例:print(calculator(2)('+')('5')('-')(3)('-')(1)('=')) 结果为 3。有什么提示吗? (如果可能的话,我宁愿不使用任何导入和全局变量!)

【问题讨论】:

  • 你可以使用def func(*arg)这样func可以接受可变数量的参数,这些参数将作为一个元组保存在arg中。您可以使用 len(arg) 在 func 中查看 args 编号,并将它们作为普通元组访问。
  • 但参数必须按照我写的特定顺序传递: print(calculator(2)('+')('5')('-')(3)('-' )(1)('='))

标签: python function recursion calculator nested-function


【解决方案1】:

您可以编写计算器来接受任何输入 t 和默认的 lambda 累加器 r -

def calculator(t, r = lambda a: a):
  if isinstance(t, int):
    return lambda next: \
      calculator(next, lambda _: r(t))
  elif t == "+":
    return lambda next: \
      calculator(next, lambda a: r(0) + a)
  elif t == "-":
    return lambda next: \
      calculator(next, lambda a: r(0) - a)
  # else any other operation:
    # ...
  elif t == "=":
    return r(0)
print(calculator(2)('+')(5)('-')(3)('-')(1)('='))
2 + 5 - 3 - 1 =
7 - 3 - 1 =
4 - 1 =
3

即使在“覆盖”操作时,这也能可靠地工作 -

calculator(5)("+")("-")(3)("=")       # 2
calculator(5)("+")("-")("+")(3)("=")  # 8

但是,当提供多个数字而没有将它们组合起来的操作时,情况就不那么好了 -

calculator(5)(4)(3)("=")  # 5

这是一个看似玩具作业的玩具程序,但是我认为如果您认为袖珍计算器算术可以是一种有趣的方式来实现您的第一语言,那么还有很多东西需要学习。详情请见this Q&A

为了澄清我的意思,考虑一下calc 的这个大大简化的版本-

def calc(t, r = ()):
  if t == "=":
    return r
  else:
    return lambda next: \
      calc(next, (*r, t))
print(calc(2)('+')(5)('-')(3)('-')(1)('='))
print(calc(5)("+")("-")(3)("="))
print(calc(5)("+")("-")("+")(3)("="))
print(calc(5)(4)(3)("="))
(2, '+', 5, '-', 3, '-', 1)
(5, '+', '-', 3)
(5, '+', '-', '+', 3)
(5, 4, 3)

calc 没有尝试在超级复杂函数中计算所有内容,而是形成了一个结果 表达式r。在最后一步中,我们可以使用您预期的操作顺序进行标记和解析以计算所需的结果,而不是将表达式作为输出返回 -

def calc(t, r = ()):
  if t == "=":
    return eval(parse(tokenize(r))) # <--
  else:
    return lambda next: \
      calc(next, (*r, t))

def tokenize(t):
  # ...

def parse(t):
  # ...

def eval(t):
  # ...

这使您能够恰当地处理诸如

之类的表达式
calc(5)(3)("+")(1)(0)(7)("*")(2)("=")

也许标记为 -

53 + 107 * 2 =

并以从左到右的操作顺序进行评估 -

53 + 107 * 2 =
160 * 2 =
320

或者使用 PEMDAS 进行评估,例如 -

53 + 107 * 2 =
53 + 214 =
267

实现tokenizeparseeval 留给读者作为练习。如果您有任何问题,我很乐意为您提供帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多