我编写了一个脚本,该脚本遍历字符串列表,并在文件的(1)行或目录的(2)文件名中查找匹配项。
根据搜索模式(用户输入),如果(1)完全匹配行/文件名或(2)包含该行/文件名,则将每个字符串追加到列表中。
import os
import operator
query_list = ["look", "for", "these"]
search_object = "name_of_file_or_directory"
if os.path.isfile(search_object):
input_object = 1
with open(search_object, "r") as file:
lines = file.read().split("\n")
elif os.path.isdir(search_object):
input_object = 2
search_mode = input("Are you looking for objects that (1) exactly match or (2) contain the query? ")
matched = []
def comparison():
if search_mode == "1" and operator.eq(string, query) or search_mode == "2" and operator.contains(string, query):
matched.append(string)
return matched
for query in query_list:
def search_loop(container):
# container is either list of filenames or list of lines
global string
for string in container:
matched = comparison()
return matched
if input_object == 1:
matched = search_loop(lines)
elif input_object == 2:
matched = search_loop(os.listdir(search_object))
print(matched)
我定义了comparison()
函数,因此以后可以在脚本中更频繁地使用它,而无需重复这些行。但是,然后我必须在其他函数中分配global string
,否则会收到以下错误。
NameError: name 'string' is not defined
我想知道如何避免使用全局变量。我读到,通常可以使用类来避免这种情况,但是我无法弄清楚这在这里有什么用。感谢您提供有关如何很好地解决此问题的建议。
答案 0 :(得分:1)
我们可以采取一些措施来清理代码。最后,我们将摆脱全局变量。
我们不必等到最后才获得目录内容,而是可以从一开始就获得它。这样,以后我们就可以完全相同地对待文本行和目录内容。
const options = {
disableStorageKey: true,
onFileSelected: updateStorePath,
fromSources: ['local_file_system', 'dropbox'],
storeTo: {
access: 'private',
container: 'myContainer',
location: 's3',
region: 'us-east-2',
path: ''
}
};
function updateStorePath (file) {
file.size # I can access size
< not sure how to proceed >
}
之前,我们每次都要检查执行哪种操作(完全匹配或包含)。相反,我们可以在获得用户输入时选择正确的选项,并将其分配给单个名称以供以后使用。
import os
import operator
query_list = ["look", "for", "these"]
search_object = "name_of_file_or_directory"
if os.path.isfile(search_object):
with open(search_object, "r") as file:
lines = file.read().split("\n")
elif os.path.isdir(search_object):
lines = os.listdir(search_object)
# At this point, lines is just a list of text - we don't care where it came from.
search_mode = input("Are you looking for objects that (1) exactly match or (2) contain the query? ")
matched = []
def comparison():
if search_mode == "1" and operator.eq(string, query) or search_mode == "2" and operator.contains(string, query):
matched.append(string)
return matched
for query in query_list:
def search_loop(container):
# container is either list of filenames or list of lines
global string
for string in container:
matched = comparison()
return matched
# We were able to remove checks from here
matched = search_loop(lines)
print(matched)
现在,我们对程序的各个部分有了更好的了解,我们可以将其分解为功能。使用函数为程序的各个部分提供了具体的名称,还有助于缩小它们使用的变量的范围。任何一段代码中使用的变量越少,以后就越容易理解。我们通过仔细选择函数来避免全局变量-我们可能使用的一个重要标准是函数中的所有内容都是自包含的,不需要引用任何外部内容。
我们还将使用import os
import operator
query_list = ["look", "for", "these"]
search_object = "name_of_file_or_directory"
if os.path.isfile(search_object):
with open(search_object, "r") as file:
lines = file.read().split("\n")
elif os.path.isdir(search_object):
lines = os.listdir(search_object)
search_mode = input("Are you looking for objects that (1) exactly match or (2) contain the query? ")
# Because the interface of both functions is the same we can use them directly.
# If they were not the same then we could write an adapter function that would make them have
# the same signatures so they could be used in the same way below.
if search_mode == "1":
search_op = operator.eq
elif search_mode == "2":
search_op = operator.contains
matched = []
for query in query_list:
for string in lines:
if search_op(string, query):
matched.append(string)
print(matched)
约定,因此如果需要,我们可以从另一个脚本中包含我们的脚本。
if __name__ == '__main__'
import os
import operator
def get_contents(search_object):
if os.path.isfile(search_object):
with open(search_object, "r") as file:
return file.read().split("\n")
elif os.path.isdir(search_object):
return os.listdir(search_object)
def get_search_function(user_input):
if search_mode == "1":
return operator.eq
elif search_mode == "2":
return operator.contains
def find_matches(match_function, query_list, lines):
matched = []
for query in query_list:
for string in lines:
if match_function(string, query):
matched.append(string)
return matched
if __name__ == "__main__":
search_object = "name_of_file_or_directory"
lines = get_contents(search_object)
search_mode_input = input("Are you looking for objects that (1) exactly match or (2) contain the query? ")
search_function = get_search_function(search_mode_input)
query_list = ["look", "for", "these"]
matches = find_matches(search_function, query_list, lines)
print(matches)
适当的错误(对于可以处理的错误)或raise
(对于我们不希望发生且无法真正恢复的错误)来自)。argparse
这样的模块可以更轻松地将参数带入脚本,因此我们不必对变量值进行硬编码。assert
中读取内容,并留给用户以某种方式生成文本并将其通过管道传递给程序,例如:sys.stdin
表示目录中的内容或cat words.txt | python script.py
表示目录中的文件。