Python - 我不应该做的事情?

Enr*_* Jr 4 python

我有几个关于Python最佳实践的问题.不久前我会用我的代码做这样的事情:

...
junk_block = "".join(open("foo.txt","rb").read().split())
...
Run Code Online (Sandbox Code Playgroud)

我不再这样做,因为我可以看到它使代码更难阅读,但如果我将语句拆分为这样,代码运行会更慢:

f_obj = open("foo.txt", "rb")
f_data = f_obj.read()
f_data_list = f_data.split()
junk_block = "".join(f_data_list)
Run Code Online (Sandbox Code Playgroud)

我还注意到,没有什么可以阻止你在功能块中进行'导入',有什么理由我应该这样做吗?

Ale*_*lli 21

只要你在一个函数内部(而不是在模块顶层),将中间结果分配给本地裸名称的成本基本上可以忽略不计(在模块顶层,分配给"本地"的分号意味着在字典上搅拌 -模块__dict__- 并且比函数内的成本高得多;补救措施是永远不要在模块顶层拥有"实质性"代码......总是在函数中存储大量代码! - ).

Python的一般哲学包括"扁平比嵌套更好" - 并且包括高度"嵌套"表达式.看看你原来的例子......:

junk_block = "".join(open("foo.txt","rb").read().split())
Run Code Online (Sandbox Code Playgroud)

提出了另一个重要问题:该文件什么时候关闭?在今天的CPython中,你不必担心 - 在实践中引用计数确保及时关闭.但是大多数其他Python实现(JVM上的Jython,.NET上的IronPython,各种后端上的PyPy,Parrot上的pynie,LLVM上的Unladen Swallow,如果它根据其发布的路线图成熟,......)保证使用引用计数 - 可能涉及许多垃圾收集策略,具有各种其他优点.

没有任何保证引用计数(甚至在CPython中它总是被认为是一个实现工件,而不是语言语义的一部分!),通过在紧密循环中执行这样的"开放但没有关闭"的代码,你可能会耗费资源 -垃圾收集是由内存稀缺引发的,并不考虑其他有限的资源,如文件描述符.从2.6(和2.5,带有"从未来导入")开始,Python通过with语句支持的RAII("资源获取是初始化")方法提供了一个很好的解决方案:

with open("foo.txt","rb") as f:
  junk_block = "".join(f.read().split())
Run Code Online (Sandbox Code Playgroud)

是最简单的"unnested"方式,可确保在所有兼容的Python版本中及时关闭文件.更强大的语义使它更可取.

除了确保正确,谨慎;-),语义之外,在这样的表达式的嵌套和扁平版本之间没有太多选择.鉴于任务"从文件的内容中删除所有空格的运行",我很想基于字符串re.translate方法对基础上的替代方法进行基准测试(后者,尤其是Python 2.*,通常是最快的删除方法)所有人物来自某个集合!),在确定"拆分并重新加入"的方法之前,如果事实证明它更快 - 但这确实是一个相当不同的问题;-).