в чем разница между File.open () и open () [duplicate]

Очень простой подход, не зависящий от версии python, отсутствовал в уже заданных ответах, которые вы можете использовать большую часть времени (по крайней мере, я):

new_list = my_list * 1       #Solution 1 when you are not using nested lists

Однако, если my_list содержит другие контейнеры ( например, вложенных списков), вы должны использовать функцию глубокой печати, как другие, предложенные в ответах выше, из библиотеки копий. Например:

import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists

.Bonus: Если вы не хотите копировать элементы, используйте (ака мелкой копии):

new_list = my_list[:]

Давайте понимать разницу между решением # 1 и Solution # 2

>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55 
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

Как вы можете видеть, решение № 1 отлично работало, когда мы не использовали вложенные списки. Давайте проверим, что произойдет, когда мы применим решение №1 к вложенным спискам.

>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]   #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]       #Solution #2 - DeepCopy worked in nested list
49
задан David Grayson 12 July 2014 в 01:49
поделиться

1 ответ

Существуют важные различия между этими тремя вариантами.

File.open("file").each_line { |line| puts line }

  • File.open открывает локальный файл и возвращает файл-объект
  • файл остается открытым до тех пор, пока вы не назовете IO#close на нем

open("file").each_line { |line| puts line }

Kernel.open смотрит на строку, чтобы решить, что с ней делать.

open(".irbrc").class # => File
open("http://google.com/").class # => StringIO
File.open("http://google.com/") # => Errno::ENOENT: No such file or directory - http://google.com/

Во втором случае объект StringIO, возвращенный Kernel#open, фактически содержит содержимое http://google.com/ . Если Kernel#open возвращает объект File, он остается открытым, пока вы не назовете IO#close на нем.

IO.foreach("file") { |line| puts line }

  • IO.foreach открывает файл, называет данный блок для каждой прочитанной строки и закрывает файл впоследствии.
  • Вам не нужно беспокоиться о закрытии файла.

File.read("file").each { |line| puts line }

Вы не упомянули об этом выборе, но это тот, который я использовал бы в большинстве случаев.

  • File.read полностью читает файл и возвращает его как строку.
  • Вам не нужно беспокоиться о закрытии файла.
  • По сравнению с IO.foreach это дает понять, что вы имеете дело с файлом.
  • Сложность памяти для этого - O (n). Если вы знаете, что имеете дело с небольшим файлом, это не является недостатком. Но если это может быть большой файл, и вы знаете, что ваша сложность памяти может быть меньше, чем O (n), не используйте этот выбор.

В этой ситуации это не удается:

 s= File.read("/dev/zero") # => never terminates
 s.each …

ri

ri - это инструмент, который показывает вам рубиновую документацию. Вы используете его так же на своей оболочке.

ri File.open
ri open
ri IO.foreach
ri File#each_line

С этим вы можете найти почти все, что я написал здесь, и многое другое.

79
ответ дан Alan Gabbianelli 21 August 2018 в 10:36
поделиться
  • 1
    Престижность для вежливого напоминания ri - RTFM джентльмена. – Fábio Batista 22 February 2011 в 01:30
  • 2
    Спасибо за указатель на ri. Однако это может быть более дружелюбным. "ri File.open" ничего не нашел для меня. Попытка найти "открыть" В конечном итоге я нахожу Kernel # orig_open, а затем попытаюсь найти «Ядро # open». только для того, чтобы сказать, что есть несколько совпадений без какого-либо очевидного способа просто дать мне документы для того, чтобы точно открыть ядро ​​# вместо поиска ядра # open *. – Wodin 6 October 2012 в 11:10
  • 3
    В моей системе ri File.open работает. – johannes 8 October 2012 в 09:02
  • 4
    Если вы передадите блок в File.open, он будет автоматически закрыт, когда блок завершится, нет необходимости называть IO#close – Tombart 5 February 2013 в 23:34
  • 5
    Файл является подклассом IO, поэтому вы можете использовать File.foreach вместо IO.foreach, если вы хотите сделать его более самодокументирующим, что вы работаете с файлом. Имейте в виду, что File.read () каждый загружает весь файл в память. Если вы работаете с большими файлами, это не рекомендуется. Я бы придерживался File.foreach. – Jason Heiss 12 December 2013 в 23:40
Другие вопросы по тегам:

Похожие вопросы: