使Python脚本面向对象 [英] Making a Python script Object-Oriented

查看:63
本文介绍了使Python脚本面向对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆