В Python 3.x, raw_input
был переименован в input
, а Python 2.x input
удален.
Это означает, что так же, как raw_input
, input
в Python 3.x всегда возвращает строковый объект.
Чтобы устранить проблему, вам нужно явно вставить эти вводы в целые числа, поместив их в int
:
x = int(input("Enter a number: "))
y = int(input("Enter a number: "))
Кроме того, Python не нужен / не использует точки с запятой для завершения строк. Итак, если они не делают ничего позитивного.
Вы на правильном пути: если вы хотите использовать шаблоны fnmatch
-типов, вы должны использовать fnmatch.filter
.
Но есть три проблемы, которые делают это не совсем тривиальным.
Во-первых, вы хотите применить несколько фильтров. Как ты это делаешь? Вызов filter
несколько раз:
for ignore in ignore_files:
filenames = fnmatch.filter(filenames, ignore)
Во-вторых, вы действительно хотите сделать reverse из filter
: вернуть подмножество имен, которые не . Как объясняет документация:
Это то же самое, что и
blockquote>[n for n in names if fnmatch(n, pattern)]
, но реализовано более эффективно.Итак, чтобы сделать наоборот, вы просто бросаете в
not
:for ignore in ignore_files: filenames = [n for n in filenames if not fnmatch(n, ignore)]
Наконец, вы пытаетесь фильтровать частичные имена путей, а не только имена файлов, но вы не выполняете
join
до тех пор, пока не будет фильтрация. Итак, переключите порядок:filenames = [os.path.join(root, filename) for filename in filenames] for ignore in ignore_files: filenames = [n for n in filenames if not fnmatch(n, ignore)] matches.extend(filenames)
Есть несколько способов улучшить это.
Вы можете использовать выражение генератора вместо понимания списка (вместо скобок квадратных скобок), поэтому, если у вас есть огромные списки имен файлов, вы используете ленивый конвейер вместо того, чтобы тратить время и пространство на многократное построение огромных списков.
Кроме того, может быть и не проще понять, если вы инвертируете порядок циклов, например:
filenames = (n for n in filenames if not any(fnmatch(n, ignore) for ignore in ignore_files))
Наконец, если вас беспокоит производительность, вы можете использовать
fnmatch.translate
для каждого выражения, чтобы превратить их в эквивалентные регулярные выражения, а затем объединить их в одно большое регулярное выражение и скомпилировать его, и использовать это вместо цикла вокругfnmatch
. Это может оказаться сложным, если ваши шаблоны могут быть более сложными, чем просто*.jpg
, и я бы не рекомендовал его, если вы действительно не определяете узкое место производительности здесь. Но если вам нужно это сделать, я видел, по крайней мере, один вопрос о SO, где кто-то приложил много усилий, чтобы выбить все крайние случаи, поэтому поиск вместо того, чтобы пытаться написать его самостоятельно.
matches.extend([fn for fn if not filename in ignore_files])
Должен сделать трюк для простых имен файлов, для игнорирования шаблонов что-то вроде:
def reject(filename, filter):
""" Takes a filename and a filter to reject files that match."""
if len(filter)==0:
return False
else:
return fnmatch.fnmach(filename, filter[0]) or reject(filename, filter[1:])
matches.extend([os.path.join(root, fn) for fn in filenames if not reject(fn, ignore_files)])
Вышеупомянутое будет при создании списка из имен файлов в os.walk проверке, что ни одна из фильтры обеспечивают совпадение - фильтры проверяются до тех пор, пока не останется ни одного, либо найдено первое совпадение, поэтому оно должно быть довольно быстрым.
Вы также можете попробовать что-то вроде:
filenames = set(filenames) # convert to a set
for filter in ignore_files:
filenames = filenames - set(fnmatch.filter(filenames, filter)) # remove the matches
matches.extend([os.path.join(root, fn) for fn in filenames]) # Add to matches
ignore_files
- список простых имен файлов, .gitignore
и fnmatch
разрешают шаблоны glob, и это чрезвычайно полезно. В OP есть пример (*.jpg
).
– user
10 August 2014 в 15:37
in filenames
между for fn
и if not
. Вам нужно добавить его, чтобы сделать эту работу. Но, как отметил Делнан, это не сработает для вас.
– abarnert
10 August 2014 в 17:53
fnmatch.filter(filenames, '*')
. Все имена файлов соответствуют*
, поэтому просто возвращает копиюfilenames
. – abarnert 10 August 2014 в 20:21.gitignore
, такие как**/a/b
,a/b/**
иa/**/b
, и, похоже, не справляется с простымfoo
. Например,foo
в .gitignore будет соответствоватьfoo
иa/foo
, но fnmatch не будет работать наa/foo
– gman 17 July 2015 в 10:40