使Python脚本面向对象 [英] Making a Python script Object-Oriented
问题描述
我正在用Python编写一个具有许多不同功能的应用程序,因此从逻辑上讲,我认为最好将脚本拆分为不同的模块.目前,我的脚本正在读取一个文本文件,其中包含已转换为标记和拼写的代码.然后,脚本将代码重新构造为字符串,并在其中带有空白行的地方将在原始代码中添加注释.
I'm writing an application in Python that is going to have a lot of different functions, so logically I thought it would be best to split up my script into different modules. Currently my script reads in a text file that contains code which has been converted into tokens and spellings. The script then reconstructs the code into a string, with blank lines where comments would have been in the original code.
我在使脚本面向对象时遇到了问题.无论我如何尝试,我似乎都无法像运行单个脚本文件一样使程序运行.理想情况下,我希望有两个脚本文件,一个包含一个清理和重构该文件的类和函数的脚本文件.第二个脚本将简单地从另一个文件中的类调用该函数,该文件位于命令行中作为自变量指定的文件中.这是我当前的脚本:
I'm having a problem making the script object-oriented though. Whatever I try I can't seem to get the program running the same way it would as if it was just a single script file. Ideally I'd like to have two script files, one that contains a class and function that cleans and reconstructs the file. The second script would simply call the function from the class in the other file on a file given as an argument from the command line. This is my current script:
import sys
tokenList = open(sys.argv[1], 'r')
cleanedInput = ''
prevLine = 0
for line in tokenList:
if line.startswith('LINE:'):
lineNo = int(line.split(':', 1)[1].strip())
diff = lineNo - prevLine - 1
if diff == 0:
cleanedInput += '\n'
if diff == 1:
cleanedInput += '\n\n'
else:
cleanedInput += '\n' * diff
prevLine = lineNo
continue
cleanedLine = line.split(':', 1)[1].strip()
cleanedInput += cleanedLine + ' '
print cleanedInput
在遵循了以下Alex Martelli的建议之后,我现在有了以下代码,它的输出与原始代码相同.
After following Alex Martelli advice below, I now have the following code which gives me the same output as my original code.
def main():
tokenList = open(sys.argv[1], 'r')
cleanedInput = []
prevLine = 0
for line in tokenList:
if line.startswith('LINE:'):
lineNo = int(line.split(':', 1)[1].strip())
diff = lineNo - prevLine - 1
if diff == 0:
cleanedInput.append('\n')
if diff == 1:
cleanedInput.append('\n\n')
else:
cleanedInput.append('\n' * diff)
prevLine = lineNo
continue
cleanedLine = line.split(':', 1)[1].strip()
cleanedInput.append(cleanedLine + ' ')
print cleanedInput
if __name__ == '__main__':
main()
尽管如此,我仍然想将我的代码分成多个模块.我程序中的已清除文件"还会执行其他功能,所以自然而然地,已清除文件应该本身就是一个类?
I would still like to split my code into multiple modules though. A 'cleaned file' in my program will have other functions performed on it so naturally a cleaned file should be a class in its own right?
推荐答案
要显着提高现有代码的速度,请在分配给tokenList
之前添加def main():
,缩进这4个空格后的所有内容,最后将惯用语
To speed up your existing code measurably, add def main():
before the assignment to tokenList
, indent everything after that 4 spaces, and at the end put the usual idiom
if __name__ == '__main__':
main()
(实际上并不需要保护罩,但是这是一个好习惯,因为对于具有可重用功能的脚本,可以使它们可从其他模块导入).
(The guard is not actually necessary, but it's a good habit to have nevertheless since, for scripts with reusable functions, it makes them importable from other modules).
这与面向对象"的任何事情都没有关系:在Python中,将所有实质性代码保留在函数中(而不是作为顶层模块代码 )只是简单得多.
This has little to do with "object oriented" anything: it's simply faster, in Python, to keep all your substantial code in functions, not as top-level module code.
第二次加速,将cleanedInput
更改为列表,即其第一项分配应为= []
,并且无论现在何处具有+=
,都应使用.append
.最后,''.join(cleanedInput)
以获得最终的结果字符串.这使您的代码将线性时间作为输入大小的函数(O(N)
是通常的表达方式),而当前则需要二次时间(O(N squared)
).
Second speedup, change cleanedInput
into a list, i.e., its first assignment should be = []
, and wherever you now have +=
, use .append
instead. At the end, ''.join(cleanedInput)
to get the final resulting string. This makes your code take linear time as a function of input size (O(N)
is the normal way of expressing this) while it currently takes quadratic time (O(N squared)
).
然后,正确:continue
之后的两个语句永远不会执行.您是否需要它们?如果不需要,请删除它们(和continue
),如果实际上需要这两个语句,请删除continue
.除非执行先前的if
,否则从if diff
开始的测试将严重失败,因为那时diff
将是未定义的.您发布的代码是否可能存在缩进错误,即您发布的内容的缩进与实际代码不同吗?
Then, correctness: the two statements right after continue
never execute. Do you need them or not? Remove them (and the continue
) if not needed, remove the continue
if those two statements are actually needed. And the tests starting with if diff
will fail dramatically unless the previous if
was executed, because diff
would be undefined then. Does your code as posted perhaps have indentation errors, i.e., is the indentation of what you posted different from that of your actual code?
考虑到这些重要的必要增强功能,以及很难看到您在制作此小代码OO(和/或模块化)时所追求的优势,我建议澄清一下缩进/正确性的情况,并应用我已经实现的增强功能提出来,然后留在那儿;-).
Considering these important needed enhancements, and the fact that it's hard to see what advantage you are pursuing in making this tiny code OO (and/or modular), I suggest clarifying the indenting / correctness situation, applying the enhancements I've proposed, and leaving it at that;-).
编辑:由于OP现在已应用了我的大部分建议,因此,让我以一种合理的方式跟进,将大多数功能分解为单独模块中的类.在一个新文件中,例如foobar.py
,在与原始脚本相同的目录中(或在site-packages
中,或在sys.path
的其他位置)中,放置以下代码:
Edit: as the OP has now applied most of my suggestions, let me follow up with one reasonable way to hive off most functionality to a class in a separate module. In a new file, for example foobar.py
, in the same directory as the original script (or in site-packages
, or elsewhere on sys.path
), place this code:
def token_of(line):
return line.partition(':')[-1].strip()
class FileParser(object):
def __init__(self, filename):
self.tokenList = open(filename, 'r')
def cleaned_input(self):
cleanedInput = []
prevLine = 0
for line in self.tokenList:
if line.startswith('LINE:'):
lineNo = int(token_of(line))
diff = lineNo - prevLine - 1
cleanedInput.append('\n' * (diff if diff>1 else diff+1))
prevLine = lineNo
else:
cleanedLine = token_of(line)
cleanedInput.append(cleanedLine + ' ')
return cleanedInput
您的主脚本将变为:
import sys
import foobar
def main():
thefile = foobar.FileParser(sys.argv[1])
print thefile.cleaned_input()
if __name__ == '__main__':
main()
这篇关于使Python脚本面向对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!