【问题标题】:How to find datatype of input data如何查找输入数据的数据类型
【发布时间】:2019-01-17 07:37:19
【问题描述】:

我是 python 新手,我的程序是一个简单的加法程序,它可以添加用户输入的任何数字(int 或 float),并且循环在输入 q 时停止。现在我的问题是我每次输入一些数字然后输入 q 停止时都会收到"ValueError"

我已经使用eval() 函数来确定输入数据的数据类型。我在一个无限循环中添加了我的添加,该循环在输入 q 时中断。

这是我的代码:

sum,sum_i,c=0,0,0
sum_f=0.0

print("Enter q/Q to stop entering numbers.")
while True:
    a=input("Enter number: ")
    try:
        t= eval(a)
        print(type(t))
    except (NameError, ValueError):
        pass

    if(type(t)==int):
        sum_i=sum_i+int(a)
        c=c+1

    elif(type(t)==float):
        sum_f=sum_f+float(a)
        c=c+1

    elif (type(t)==str):
        if (a=='q'or a=='Q'):
            break

    else:
            print("Invalid data entered. Please enter a number to add or q/Q to quit. ")

sum= sum_i+ sum_f
print("You have entered ",c," numbers and their sum is: ",sum)

我的输出应该提供输入 q 时输入的数字的总和,但这是我得到的:

Enter q/Q to stop entering numbers.
Enter number: 3
<class 'int'>
Enter number: 5.5
<class 'float'>
Enter number: 12
<class 'int'>
Enter number: q
Traceback (most recent call last):
  File "/home/netvarth/py test/sum.py", line 14, in <module>
    sum_i=sum_i+int(a)
ValueError: invalid literal for int() with base 10: 'q'

【问题讨论】:

  • 出于安全原因,一般的良好做法是使用import astast.literal_eval() 而不是eval()
  • @Archie 我知道这不是真正的生产代码,但永远不要在用户的原始输入上使用eval()。用户只需输入sys.exit(0) 之类的内容并关闭您的系统
  • eval('q') -> NameError; t 仍然是以前的样子。如果是int,您将尝试int('q'),它会产生您的ValueError

标签: python python-3.x


【解决方案1】:

这是使用嵌套 try/except 进行的重构,它以更简洁和 Python 的方式解决了问题。

#!/usr/bin/env python3

nums = list()
while True:
    # Usability tweak: Trim surrounding whitespace
    a = input("Enter number: ").strip()
    try:
        t = int(a)
    except ValueError:
        try:
            t = float(a)
        except ValueError:
            if a in ('q', 'Q'):
                break
            print("Invalid data entered. Please enter a number or q/Q to quit.")
            continue
    nums.append(t)
print("You have entered {0} numbers and their sum is {1}".format(
    len(nums), sum(nums)))

【讨论】:

    【解决方案2】:

    两件事:首先检查一种更适合使用pythonian的东西

       isinstance(t, int)
    

    但第二件事是你的代码失败了。

    如果你评估一个文字,你很可能会得到一个名称错误,因为变量没有在任何地方定义。但是,例如,如果您输入“c”,您会完全得到一些奇怪的东西。由于变量 c 已定义,因此不会出现名称错误,但在将文字 'c' 转换为 int 时仍然会失败。

    您可以使用正则表达式来检查输入是否为数字

    例如像这样。

        if re.match('(\d+(\.\d+)?)', a):
            try:
                t = eval(a)
                print(type(t))
            except (NameError, ValueError):
                pass
        elif a == 'q' or a == 'Q':
            break
        else:
            continue
    
        if isinstance(t, int):
            sum_i = sum_i + int(a)
            c = c + 1
    
        elif isinstance(t, float):
            sum_f = sum_f + float(a)
            c = c + 1
        else:
            print("Invalid data entered. Please enter a number to add or q/Q to quit. ")
    

    【讨论】:

    • 首先您检查输入字符串是否与整数或浮点数的模式匹配 \d: 数字 +: 至少一个 ?: 不是强制性的,如果输入值与模式匹配,您可以将其评估为 int 或如果不是这种情况,则浮动,我们假设它是一个字符串并且能够检查您的退出条件
    • 我不能在没有 eval() 部分的情况下使用 isinstance() 吗?我尝试时出错。
    • 我取出了 try 块,而是在正则表达式 if 下添加了 int 和 float 的 if 部分。我的输出:输入 q/Q 停止输入数字。输入数字:3 输入数字:5.8 输入数字:15 输入数字:q 输出到此结束。
    • 我不太关注你。程序失败了吗?你得到什么输出?对我来说它是有效的文件,如果我输入你建议的数字,我会得到结果You have entered 3 numbers and their sum is: 23.8
    【解决方案3】:

    您的问题在于使用eval。如果它无法将字符串解析为变量,它应该会失败,但在您的情况下,您已经有一个 t 在命名空间中浮动。 t 将其旧标识保留为 int,但随后您尝试将 a(字符串)添加到数字。

    这段代码应该可以工作:

    sum,sum_i,c=0,0,0
    sum_f=0.0
    
    print("Enter q/Q to stop entering numbers.")
    while True:
        a=input("Enter number: ")
        try:
            t = int(a)
            sum_i=sum_i+int(a)
            c=c+1
            print(type(t))
            continue
        except ValueError:
            pass
    
        try:
            t = float(a)
            sum_f=sum_f+int(a)
            c=c+1
            print(type(t))
            continue
        except ValueError:
            pass
    
        try:
            if (a=='q'or a=='Q'):
                break
            else:
                print("Invalid data entered. Please enter a number to add or q/Q to quit. ")
                continue
        except ValueError:
            pass
    sum= sum_i+ sum_f
    print("You have entered ",c," numbers and their sum is: ",sum)
    

    【讨论】:

    • NameError 是怎么回事?
    • 哦,是的 - 我从 OP 的代码中复制了它,但我会删除它
    • 我在尝试某事时遇到过一次 NameError,因此将其添加到了例外中。 :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    相关资源
    最近更新 更多