【问题标题】:Using Python Interactive as a Programming Calculator使用 Python Interactive 作为编程计算器
【发布时间】:2016-06-01 07:39:37
【问题描述】:

多年来,我一直使用AnalogX PCalc 作为计算器进行封底交互式计算,其中整数数学很重要,灵活的基本输入和输出很重要。例如,在处理定点数时,通常同时使用十进制或十六进制的数字视图都无助于解决问题。它还内置了漂亮的 C 数学函数,以及返回整数的字符串函数。缺点很明显,它的功能集有限,而且仅限 Windows。

我在想 Python 交互式计算器会是一个更好的计算器,如果你只关心一个基数而不关心整数数学恶作剧,它通常已经是这样了。但至少对于这两个约束,它并不是那么好。因此,至少,是否有可能让 Python 交互以打印多个基数的整数,或者以 10 为基数的另一个基数,而无需每次都预先添加“hex()”?

【问题讨论】:

  • 你不能只创建一个小模块,它的功能可以输出所有所需格式的数字吗?
  • 查看 decimal 模块,Decimal 类型的子类可以很容易地以首选格式输出,并且在进行除法时不会遇到浮点精度问题。

标签: python math numerical


【解决方案1】:

Python 标准库提供了codecodeop 模块,因此REPL 的功能也可以在其他程序中使用。

例如,这里是一个示例 Python 文件,它扩展了标准库类以提供一个新的交互式控制台,可以将整数结果转换为其他基数(目前支持基数 2 和 16,但添加其他基数应该很容易)。使用了几行额外的代码来支持 Python 2 和 3。

#!/usr/bin/env python
from __future__ import print_function

import sys
import code

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO


class NumericConsole(code.InteractiveConsole):
    def __init__(self, *args, **kwargs):
        code.InteractiveConsole.__init__(self, *args, **kwargs)
        self.base = 10

    def runcode(self, code_to_run):
        return_val, output = self._call_and_capture_output(code.InteractiveConsole.runcode, self, code_to_run)
        try:
            output = self._to_target_base(output) + '\n'
        except ValueError:
            pass
        print(output, end='')
        return return_val

    def _to_target_base(self, value):
        # this can be extended to support more bases other than 2 or 16
        as_int = int(value.strip())
        number_to_base_funcs = {16: hex, 2: bin}
        return number_to_base_funcs.get(self.base, str)(as_int)

    def _call_and_capture_output(self, func, *args, **kwargs):
        output_buffer = StringIO()
        stdout = sys.stdout
        try:
            sys.stdout = output_buffer
            func_return = func(*args, **kwargs)
        finally:
            sys.stdout = stdout
        return (func_return, output_buffer.getvalue())


def interact(base=10):
    console = NumericConsole()
    console.base = base
    console.interact()


if __name__ == '__main__':
    base = len(sys.argv) > 1 and int(sys.argv[1]) or 10
    interact(base)

现在您可以运行此脚本并将所需的基数作为第一个 CLI 参数传递:

$ python <this_script> 16

如果任何表达式的结果是整数,它将以十六进制格式打印。

当然可以添加更多的基数(假设您将有一个函数将十进制值转换为该基数),并且有更漂亮的方法来传递 CLI 参数。

【讨论】:

  • 这是一个很好的开始。这绝对可以扩展为在功能上接近多基输出,同时在功能上更优越。唯一的缺点是脚本需要在运行的机器上,因为安装钩子不是很简单。
猜你喜欢
  • 1970-01-01
  • 2022-06-15
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
  • 2015-04-29
  • 1970-01-01
相关资源
最近更新 更多