【问题标题】:Python read stuff from file, C++ stylePython 从文件中读取内容,C++ 风格
【发布时间】:2017-04-04 17:14:56
【问题描述】:

我有这个 C++

int n = 0;
file >> n;

for (int i = 0; i < n; i++) file >> array[i];

etc.

如何在 Python 中简洁地编写它?

这是 Python:

string = string.lstrip()

n = 0
for c in string:
  if not c.isdigit():
    break
  n = n * 10 + int(c)

for i in range(n):
  string = string.lstrip()
  for c in string:
    if not c.isdigit():
      break
    array[i] = array[i] * 10 + int(c)

我认为 Python 应该比 C++ 更“富有表现力”。

【问题讨论】:

  • 你试过什么?你的代码是什么?
  • 你的问题和Python比较相关,所以我建议去掉C++语言标签。
  • @Max 你的意思是这不可行吗?我试过while c.isdigit() 但那很原始。
  • 向我们展示你觉得不如 C++“表现力”的 Python 代码。
  • @BrianRodriguez 我添加了 Python 代码

标签: python file input


【解决方案1】:

io class 告诉我们文件对象有哪些方法(open() 返回的东西)。我没有看到“read word”或“read int”之类的东西。

我本来想说的是,编写一些小函数来做到这一点很简单,但它变成了一个 4 小时的探险,变得相当大,只是作为 Stack Overflow 答案中的一个例子。我已将其发布在 Github 上:https://github.com/lgommans/OpenSesame

您需要的文件就是open_sesame.py。基本用法是:

from open_sesame import OpenSesame

myfile = OpenSesame("data.txt")
records = myfile.int()
for i in range(0, records):
    array.append(myfile.number())

我尝试注释代码并使其非常清晰,因此如果您想进行修改或查看它的作用应该是可以理解的。

【讨论】:

    【解决方案2】:

    不要手动解析字符串中的整数。 Python 完全有能力为您做到这一点:

    >>> s = "12345"
    >>> i = int(s)
    >>> print(i)
    12345
    

    这已经清理了你的大部分代码:

    string = string.lstrip()
    n = int(string)
    
    for i in range(n):
      string = string.lstrip()
      array[i] = int(string)
    

    我没有看到任何围绕字符串移动的逻辑,所以我假设你已经忽略了这些部分。您也没有明确区分这些整数的确切含义(您的代码说“任何不是数字的东西”),所以我假设它是空格分隔的。

    Python 可以通过str 中的一种方法为您拆分此类字符串:split

    >>> s = "1 2\n3\t4 5"  # Notice: all kinds of whitespace here.
    >>> arr = s.split()  # By default, split will split on whitespace.
    >>> print(arr)
    ['1', '2', '3', '4', '5']
    

    请注意,拆分将值保留为字符串。这意味着我们还没有完成,我们还必须将每个单独的元素转换为我之前演示的整数。

    在这里,我将使用称为列表推导的 Python 功能:

    >>> s = "1 2\n3\t4 5"
    >>> arr = [int(n) for n in s.split()]
    >>> print(arr)
    [1, 2, 3, 4, 5]
    

    这就是人们在提到 Python 的“表现力”时所谈论的内容:) 这将您编写的所有代码都变成了单行代码。但是,这假设您的数据已经在字符串中。您似乎正在从文件中读取数据,因此需要做更多工作才能使其正常工作...

    arr = []  # Empty list. 
    with open("path/to/file.txt") as f:
        for line in f:  # Will read all lines.
            arr += [int(x) for x in line.split()]
    # Use arr...
    

    ...假设您在一行中有多个整数。相反,如果你在每一行都有一个 int,你的代码就会变得更简单:

    with open("path/to/file.txt") as f:
        arr = [int(line) for line in f]  # Will read all lines.
    # Use arr...
    

    但是,这仍然不是您原来问题的完整解决方案......但我希望它无论如何都具有教育意义。 FWIW,这就是我将如何解决您的特定问题:

    with open("path/to/file.txt") as f:
        ints_of_f = (int(line) for line in f)  # A *GENERATOR*, not a *LIST*.
        n = next(ints_of_f)
        arr = [next(ints_of_f) for _ in range(n)]  # _ is a throwaway variable.
    

    最后,这里有一个great talk,关于如何编写“漂亮、富有表现力”的 Python 代码。

    【讨论】:

    • 准确地说,当您有多行时,您不必像for line in file 那样遍历它们,您只需read 整个文件即可。如果你想全力以赴:arr = (lambda it: [next(it) for _ in range(next(it))])(map(int, open(FILENAME).read().split()))How's 那是为了表达?
    • 对我来说,表现力是可读性,而不是字符/行数 :) 是的,您确实可以.read() 整个文件,只是要小心在非常大的文件上使用它。
    • 如果有一些读取迭代器就好了,它不需要预先读取文件,而是像标准生成器一样在需要时读取。
    • 有!它叫mmap ;)
    • 这在 Windows 上有效吗? (似乎有点)(但在 linux 上我得到 [Errno 12] Permission denied)[已解决] mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ) 谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 2012-05-18
    • 2016-08-31
    • 1970-01-01
    相关资源
    最近更新 更多