对函数中变量和参数的范围和可见性感到困惑

Confusion about the scope and visibility of variable and argument in a function

我不明白为什么 test1 和 test2 相同时会 return 2 个不同的输出。

   python3.7.4

   fin=open('D:\Python\Think Python\words.txt')

   def build_list_append(file):
       word_list=[]
       for line in fin:
           word=line.strip()
           word_list.append(word)
       return word_list

   def test1(worklist1=build_list_append(fin)):
       print("This is test1,It will return a non-empty list")
       print(len(worklist1))

   def test2(worklist2=build_list_append(fin)):
       print("This is test2,It will return an empty list")
       print(len(worklist2))

Short Answer: That's because once test1() is called, read pointer will move to end of file. Once test2() is called there are no lines left to read, hence 0 length.

长答案:

fin = open('D:\Python\Think Python\words.txt') 处,读取指针将指向文件的开头。

一旦 file1() 被调用,它将调用 build_list_append(fin) 逐行遍历文件。因此,所有行都将存储在 word_list 中,长度将被 returned.

现在,指针指向文件末尾。

调用test2()后,程序再次调用build_list_append(fin)想要逐行遍历整个文件,但是因为指针已经在文件的末尾,所以它没有任何内容可以通过。因此,长度 0 是 returned.

如果您尝试关闭文件并传递一个新的文件对象,test2() 将 return 与 test1() 相同的值。

再次尝试 运行ning 程序,除了在 函数 build_list_append() 中使用 fin = open(...) 语句 (确保添加 fin.close() 最后)。然后,他们会表现得一样。

python 中的文件对象(由 open() 编辑的那些 return)属于一个名为 generator[=29= 的对象的 class ]*。生成器是可迭代的,并且根据需要惰性地 return 个元素接一个元素。它们与列表的区别在于,您不能在生成器中 向后 - 您只能获取下一个元素。所以当你 运行 没有元素时,你什么也得不到。

这就是这里发生的事情。循环 for line in fin 在第一次执行时耗尽了文件对象可以产生的所有元素。当你再次执行它时,生成器没有更多的东西可以提供,所以 for 循环不会 运行,你会得到一个空列表。除非您从头开始重新创建生成器,否则通过再次调用 open(),它有 运行 个元素。


*比这更复杂,从技术上讲,文件对象不是生成器,但它们的行为非常相似,可以进行比较。