【问题标题】:determine the type of a value which is represented as string in python确定在python中表示为字符串的值的类型
【发布时间】:2011-01-07 08:47:50
【问题描述】:

当我在 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 中做到这一点?

【问题讨论】:

    标签: python csv types casting


    【解决方案1】:

    来自manual

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

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

    【讨论】:

      【解决方案2】:

      日期有点难。这取决于格式和它的规律性。这里有一个线索可以帮助您开始其余的工作。

      >>> 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
      

      【讨论】:

        【解决方案3】:

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

        • 日期:可能是已知格式:如果是这样,您可以尝试从时间戳字符串 (datetime.strptime()) 实例化一个日期时间,如果失败,您就知道它不是日期时间。

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

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

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

        【讨论】:

          【解决方案4】:

          嗯..你不能。

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

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

          【讨论】:

            【解决方案5】:

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

            不过,我想到了几件事。一种是进行某种模式匹配(例如,如果它包含一个小数点,它是一个浮点数等)。对于解析/猜测日期,您可以尝试thisthis

            您还可以尝试将元素“强制转换”为您想要的任何内容并捕获异常以尝试其他元素。您可以执行类似尝试 int 的操作,如果失败,请尝试 float,如果失败,请尝试 date 等。

            【讨论】:

              【解决方案6】:

              你可以这样做:

              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 测试之前。对于日期,您可以为要支持的格式添加更多测试,但显然您无法涵盖所有​​可能的情况。

              【讨论】:

              • 这正是我要给出的答案。只有我认为我会在except 子句中使用pass,而不是continue,但这是一个我们可能不想走下去的哲学兔子洞。
              • 不幸的是,getType(2010.0) 给出了
              • 使用ast.literal_eval() 可以正确区分intfloat,但不会直接集成到给定的代码中。
              【解决方案7】:

              这不能以可靠的方式完成,这不是由于 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'>
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-03-29
                • 1970-01-01
                • 2021-06-02
                • 1970-01-01
                • 2015-08-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多