Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使Python脚本面向对象_Python_Oop - Fatal编程技术网

使Python脚本面向对象

使Python脚本面向对象,python,oop,Python,Oop,我正在用Python编写一个应用程序,它将有很多不同的函数,所以从逻辑上讲,我认为最好将我的脚本分成不同的模块。目前,我的脚本读取一个文本文件,其中包含已转换为标记和拼写的代码。然后,脚本将代码重新构造为字符串,在原始代码中注释所在的位置有空行 def main(): tokenList = open(sys.argv[1], 'r') cleanedInput = [] prevLine = 0 for line in tokenList:

我正在用Python编写一个应用程序,它将有很多不同的函数,所以从逻辑上讲,我认为最好将我的脚本分成不同的模块。目前,我的脚本读取一个文本文件,其中包含已转换为标记和拼写的代码。然后,脚本将代码重新构造为字符串,在原始代码中注释所在的位置有空行

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()
但是,我在使脚本面向对象时遇到了一个问题。无论我做什么尝试,我似乎都无法让程序像运行单个脚本文件一样运行。理想情况下,我希望有两个脚本文件,其中一个包含清理和重建文件的类和函数。第二个脚本只需从另一个文件中的类调用函数,该文件作为命令行中的参数给定。这是我当前的脚本:

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建议之后,我现在有了下面的代码,它为我提供了与原始代码相同的输出

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()

不过,我仍然希望将代码拆分为多个模块。在我的程序中,一个“清理过的文件”将有其他功能在其上执行,因此清理过的文件自然应该是一个类本身?

当我执行此特定重构时,我通常从第一个文件中的初始转换开始。步骤1:将功能移动到新类中的方法中。步骤2:添加 下面的魔术调用使文件再次像脚本一样运行:

class LineCleaner:

    def cleanFile(filename):
        cleanInput = ""
        prevLine = 0
        for line in open(filename,'r'):         
           <... as in original script ..>

if __name__ == '__main__':
     cleaner = LineCleaner()
     cleaner.cleanFile(sys.argv[1]) 
class LineCleaner:
def清洁文件(文件名):
cleanInput=“”
prevLine=0
对于打开的行(文件名为'r'):
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
cleaner=LineCleaner()
cleaner.cleanFile(sys.argv[1])

要显著加快现有代码的速度,请在分配到
标记列表之前添加
def main():
,在这4个空格之后缩进所有内容,并在最后放入常用习惯用法

if __name__ == '__main__':
  main()
(实际上不需要保护,但这是一个好习惯,因为对于具有可重用函数的脚本,它使它们可以从其他模块导入)

这与“面向对象”没有什么关系:在Python中,将所有实质性代码保存在函数中比作为顶级模块代码更快

第二次加速,更改
cleanedInput
到一个列表中,即它的第一个赋值应该是
=[]
,无论您现在有
+=
,请使用
.append
。最后,
'.join(cleanedInput)
获取最终结果字符串。这使得您的代码采用线性时间作为输入大小的函数(
O(N)
是表达这一点的正常方式),而当前代码采用二次时间(
O(N平方)

然后是正确性:
continue
后面的两条语句永远不会执行。你是否需要它们?删除它们(以及
continue
),如果不需要,则删除
continue
,如果实际需要这两条语句。如果不执行前一个
if
,则以
if diff
开始的测试将显著失败,因为
diff
将没有定义。您发布的代码是否有缩进错误,即,您发布的内容的缩进是否与实际代码的缩进不同

考虑到这些重要的必要增强,并且很难看出您在制作这个小代码OO(和/或模块化)时追求的优势,我建议澄清缩进/正确性情况,应用我提出的增强,并就此为止;-)

编辑:由于OP现在已经应用了我的大部分建议,让我用一种合理的方法将大部分功能划分到单独模块中的类。在新文件中,例如
foobar.py
,与原始脚本位于同一目录中(或
网站包中,或
系统路径上的其他地方),放置以下代码:

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()

您可以创建一个函数并将所有逻辑放在其中。但是,要实现完全的“面向对象”,您可以执行以下操作:

ps-您发布的代码在
continue
行上有一个bug-它总是被执行,最后两行永远不会执行

class Cleaner:
  def __init__(...):
    ...init logic...
  def Clean(self):
    for line in open(self.tokenList):
      ...cleaning logic...
    return cleanedInput

def main(argv):
  cleaner = Cleaner(argv[1])
  print cleaner.Clean()
  return 0

if '__main__' == __name__:
  sys.exit(main(sys.argv))

如果呈现的代码都是代码,就不要添加任何类

你的代码太简单了!! OOP方法会增加不必要的复杂性

但如果还是不行。 将所有代码放入函数例如

def parse_tokenized_input(file):
    tokenList = open(file, 'r')
    cleanedInput = ''
    prevLine = 0
    #rest of code
在末尾添加:

if __name__ == '__main__':
    parse_tokenized_input(sys.argv[1])
如果代码工作正常,将函数的def放入新文件(以及所有需要的导入!) 例如mymodyle.py

现在,您的脚本将是:

from mymodule.py import parse_tokenized_input

if __name__ == '__main__':
        parse_tokenized_input(sys.argv[1])

哦,为您的函数和模块想出更好的名称(模块应该有通用名称)。

假设您有您想要的对象。你会如何使用它?换句话说,你想要什么语法?在这种情况下,我会把输入文件看作是对象。清洁过程是我希望能够对所述对象执行的功能。考虑到这一点,我希望采用for循环,并在我的输入文件类中使用cleaning函数。但是,
clean()
arg
仍然未定义。抱歉,在我准备好之前点击提交按钮。另外,我刚刚找到了代码示例widgit。sighHa,两个强迫症患者试图同时清理同一个帖子。这就像是一个疯狂的欧亨利故事,也许是“三博士的礼物”。稍微扩展一下Alex的一点:在Python中,字符串是不可变的
s+=“abc”
制作了一份全新的
s
副本,附加了
abc
。因此,如果您正在使用串联构建一个长字符串,那么您正在一次又一次地复制一个不断增长的字符串。将项目追加到列表(或使用
StringIO
模块),然后执行单个
联接