确定在python中表示为字符串的值的类型

时间:2010-01-20 16:35:59

标签: python csv types casting

当我在python中使用csv解析器读取逗号分隔文件或字符串时,所有项目都表示为字符串。见下面的例子。

import csv
a = "1,2,3,4,5"
r = csv.reader([a])
for row in r:
    d = row

d ['1', '2', '3', '4', '5'] type(d[0]) <type 'str'>

我想确定每个值是否为字符串,浮点数,整数或日期。我怎么能在python中做到这一点?

7 个答案:

答案 0 :(得分:14)

你可以这样做:

from datetime import datetime

tests = [
    # (Type, Test)
    (int, int),
    (float, float),
    (datetime, lambda value: datetime.strptime(value, "%Y/%m/%d"))
]

def getType(value):
     for typ, test in tests:
         try:
             test(value)
             return typ
         except ValueError:
             continue
     # No match
     return str

>>> getType('2010/1/12')
<type 'datetime.datetime'>
>>> getType('2010.2')
<type 'float'>
>>> getType('2010')
<type 'int'>
>>> getType('2013test')
<type 'str'>

密钥是在测试顺序中,例如int测试应该在float测试之前。对于日期,您可以为要支持的格式添加更多测试,但显然您无法涵盖所有​​可能的情况。

答案 1 :(得分:5)

这不能以可靠的方式完成,并且不是由于Python或任何其他编程语言的限制。 如果没有猜测并遵循一些规则(在此上下文中使用时通常称为Heuristics),人类无法以可预测的方式执行此操作。

因此,首先设计一些启发式方法,然后在Python中对它们进行编码。需要考虑的事项是:

  • 我们知道所有的值都是有效的字符串,因为这是我们问题的基础,所以根本没有必要检查这个。我们应该检查我们能做的其他事情,只要我们可以留下一个字符串。
  • 日期是最明显的事情,如果它们以可预测的方式格式化,例如[YYYY]-[MM]-[DD].ISO ISO 8601 date format),它们很容易与包含数字的其他文本区分开。如果日期采用的格式只有YYYYMMDD这样的数字,那么我们就会陷入困境,因为这些日期与普通数字无法区分。
  • 接下来我们将做整数,因为所有整数都是有效的浮点数,但并非所有的浮点数都是有效的整数。我们可以检查文本是否包含数字(或数字和字母A-F,如果可能是十六进制数字),在这种情况下将值视为整数。
  • 浮动将是下一个,因为它们是具有一些格式(小数点)的数字。很容易将3.14159265识别为浮点数。但是5.0可以简单地写成5也是一个有效的浮点数,但是在前面的步骤中已被捕获,即使它是预期的,也不会被识别为浮点数。
  • 任何未转换的值都可以视为字符串。

由于我上面提到的可能重叠这样的方案永远不可能100%可靠。此外,您需要支持的任何新数据类型(可能是复数)都需要自己的一组启发式算法,并且必须放在检查链中最合适的位置。检查越有可能只匹配所需的数据类型,它应该是链上面的。

现在让我们在Python中实现这一点,我上面提到的大部分启发式方法都是由Python为我们处理的,我们只需要决定应用它们的顺序:

from datetime import datetime

heuristics = (lambda value: datetime.strptime(value, "%Y-%m-%d"),
              int, float)

def convert(value):
    for type in heuristics:
        try:
            return type(value)
        except ValueError:
            continue
    # All other heuristics failed it is a string
    return value

values = ['3.14159265', '2010-01-20', '16', 'some words']

for value in values:
    converted_value = convert(value)
    print converted_value, type(converted_value)

这输出以下内容:

3.14159265 <type 'float'>
2010-01-20 00:00:00 <type 'datetime.datetime'>
16 <type 'int'>
some words <type 'str'>

答案 2 :(得分:2)

据我所知,没有真正的答案,因为这些只是字符串。它们不是整数或浮点数等等。这些是你决定的角色。例如。 1是整数还是浮点数?

但有些事情会浮现在脑海中。一种是进行某种模式匹配(例如,如果它包含一个小数点,它就是一个浮点数等)。对于解析/猜测日期,您可以尝试thisthis

您也可以尝试将元素“转换”为您想要的任何内容,并捕获异常以尝试其他元素。您可以执行类似try int的操作,如果失败,请尝试浮动,如果失败,请尝试日期等。

答案 3 :(得分:1)

您想要实现的目标很难,因为类型不明确:“1”可以是字符串,也可以是int。无论如何,你可以尝试这样的事情:

  • 日期:大概是他们采用已知格式:如果是这样,你可以尝试从时间戳字符串(datetime.strptime())实例化日期时间,如果失败,你就知道它不是日期时间。

  • 浮动:确保所有字符都是数字,并且至少有一个“。”在字符串中。然后转换为float(float(value)

  • 整数:正则表达式字符串和匹配数字。确保字符串与源字符串的长度相同然后转换(int(value)

  • 如果以上都不起作用,那就是一个字符串。

答案 4 :(得分:1)

嗯......你不能。

您如何判断“5”是指字符串还是整数? 您如何确定“20100120”是指整数还是日期?

您当然可以进行有根据的猜测,并实施某种解析顺序。首先尝试将其作为日期,然后作为浮点数,然后作为int,最后作为字符串。

答案 5 :(得分:0)

来自manual

  

返回一个读者对象   迭代给定的行   csvfile。 csvfile可以是任何对象   它支持迭代器协议   并在每次返回一个字符串   调用next()方法 - 文件对象   和列表对象都是合适的。

接口要求每次调用next()时都返回一个字符串。

答案 6 :(得分:0)

日期有点难。这取决于格式和规则。这是让你开始休息的线索。

>>> int('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'a'
>>> int('1')
1
>>> float('1')
1.0
>>> float('1.0')
1.0

但请注意:

>>> int(1.0)
1