当前位置: 首页 > 知识库问答 >
问题:

Python编码风格困境[关闭]

尹欣怿
2023-03-14

有几个众所周知的python代码样式规则,它们被认为是默认的,我试图坚持:

换行,使其不超过79个字符。

保持缩进4个空格长。

另一个常见的编程建议是

避免全局变量

换句话说,应该始终使用接受所有变量作为参数的函数,并避免直接从更高范围读取的类似Pascal的过程

然而,在某些情况下,人们肯定应该打破其中的一些规则。例如,如果涉及具有长参数列表的函数。它们有两个不同的问题:

首先,在凹凸不平的街区,剩下的空间太少了。

def function(variable1, variable2, variable3, variable4, variable5,\
variable6, variable7, variable8, variable9):
    return variable1 + variable2 + variable3 + variable4 + variable5 +\
    variable6 + variable7 + variable8 + variable9
def...
    for variable1...
        if variable 2...
            while variable3...
                if variable4...
                    for variable5...
                        ...
                                                    variable10 =\
                                                    function(\
                                                    variable1,\
                                                    variable2,\
                                                    variable3,\
                                                    variable4,\
                                                    variable5,\
                                                    variable6,\
                                                    variable7,\
                                                    variable8,\
                                                    variable9)
                                                    ...

在这里,作为结束的程序虽然被认为是一种不好的做法,但可能会变得有用:

def...
    def procedure():
        variable10 = variable1 + variable2 + variable3 + variable4 +\
        variable5 + variable6 + variable7 + variable8 + variable9
    for variable1...
        if variable 2...
            while variable3...
                if variable4...
                    for variable5...
                        ...
                                                    procedure()
                                                    ...

另一个问题(实际上是特定于python的)是性能。如果存在大量函数参数,复制函数参数的成本可能会非常高:

import time

var1 = 1
var2 = 2
var3 = 3
var4 = 4
var5 = 5
var6 = 6

def function(var1, var2, var3, var4, var5, var6):
    pass

def procedure():
    pass

starttime = time.time()
for i in range(10000000):
    function(var1, var2, var3, var4, var5, var6)
finishtime = time.time()
print('Classical function runtime: {:.3f} s'.format(finishtime - starttime))

starttime = time.time()
for i in range(10000000):
    procedure()
finishtime = time.time()
print('Procedure runtime: {:.3f} s'.format(finishtime - start time))

这将产生:

Classical function runtime: 2.447 s
Procedure runtime: 1.180 s

因此,我向有经验的开发人员提出的问题是:

是否有什么东西可以证明使用类似Pascal的过程优于经典函数,或者应该不惜任何代价避免它们,即使它们会导致代码更大、更慢?

编辑:

使用*args**kwargs只能部分解决这个问题,因为在函数调用期间仍然需要列出所有参数。此外,它也没有解决性能问题,因为参数仍在被复制。迭代工具,正如注释中提出的,也不总是适用的。在某些情况下,解决嵌套是非常棘手的(考虑下面的代码),并且需要大量的开发时间,可能会导致非常复杂的代码。

def my_function(**kwargs):
    with open(kwargs['file_a'], 'r') as input1:
        for line1 in input1:
            if kwargs['number'] % 3 == 0:
                if kwargs['number'] % 9 == 0:
                    with open(kwargs['file_0'], 'r') as input2:
                        for line2 in input2:
                            if line1.startswith('#'):
                                if line2.startswith('A'):
                                    with open('output.txt') as output1:
                                        for item in kwargs['items']:
                                            if item is in kwargs['good']:
                                                for sub in item:
                                                    if sub < 0:
                                                        result = process_vars(
                                                            kwargs['var1'],
                                                            kwargs['var2'],
                                                            kwargs['var3'],
                                                            kwargs['var4'],
                                                            kwargs['var5'],
                                                            kwargs['var6'],
                                                            kwargs['var7'],
                                                            kwargs['var8'],
                                                            kwargs['var9'],
                                                            kwargs['var10'])
                                                        output1.write(result)
                                                    elif sub >= 0 and sub < 1:
                                                        output1.write('hello')
                                                    else:
                                                        output1.write('byebye')
                                            elif len(item) > 20:
                                                item = item[: 20]
                                            else:
                                                output1.write(line2)
                                elif line2.startswith('B'):
                                    print('warning')
                                else:
                                    print('error')
                            elif line1.startswith('!'):
                                kwargs['wonders'].count += 1
                            else:
                                kwargs['threats'].append(line1)
                else:
                    kwargs['exceptions'].append(line1)
            elif kwargs['number'] % 3 == 1:
                with open(kwargs['file_1'], 'r') as input2:
                    ...
            elif kwargs['number'] % 3 == 2:
                with open(kwargs['file_2'], 'r') as input2:
                    ...

共有1个答案

督冠玉
2023-03-14

>

  • 有人已经在注释中提到了这一点:如果您有两个或更多嵌套的循环,请尝试使用itertools.product()

    如果上面的方法做不到,至少可以减少由if语句引起的缩进级别。示例:

    for abc in ..
        if (condition):
            for xyz in ...
    

    可更改为:

    for abc in ...
        if not (condition):
            continue
        for xyz in ...
    

    如果有许多参数要传递给一个方法,请尝试使用*args(一个元组中的所有参数)或**kwargs(一个判决中的所有参数)。

    编辑:根据您的具体要求,我已经编辑了给定的代码。这可能不会产生与您完全相同的结果,但会让您大致了解如何实现上述3点。

    def my_function(**kwargs):
        process_var_list = ['var1', 'var2', 'var3', 'var4', 'var5', 'var6',
                            'var7', 'var8', 'var9', 'var10']
        #Open all 3 files at one go. This will improve performance and reduce nested loops
        with open(kwargs['file_a'], 'r') as input1, open(kwargs['file_0'], 'r') as input2, open('output.txt') as output1:
            #following point 1
            for line1, line2, item in itertools.product(input1, input2, output1):
                if kwargs['number'] % 9 == 0:
                    #following point 2
                    if line1[0] not in ["#", "!"]:
                        kwargs['threats'].append(line1)
                        continue
                    elif line1.startswith('!'):
                        kwargs['wonders'].count += 1
                        continue
                    if line2[0] not in ['A', 'B']:
                        print('error')
                        continue
                    elif line2.startswith('B'):
                        print('warning')
                        continue
                    if item in kwargs['good']:
                        for sub in item:
                            if sub < 0:
                                var_args = {var: kwargs[var] for var in process_var_list}
                                #following point 3
                                result = process_vars(**var_args)
                                output1.write(result)
                            elif 1 < sub >= 0:
                                output1.write('hello')
                            else:
                                output1.write('byebye')
                    elif len(item) > 20:
                        item = item[: 20]
                    else:
                        output1.write(line2)
                elif kwargs['number'] % 3 == 0:
                    kwargs['exceptions'].append(line1)
                elif kwargs['number'] % 3 == 1:
                    with open(kwargs['file_1'], 'r') as input2:
                        pass
                elif kwargs['number'] % 3 == 2:
                    with open(kwargs['file_2'], 'r') as input2:
                        pass
    

  •  类似资料:
    • 问题内容: Python教程说:“在运算符周围和逗号后使用空格,但不要直接在括号结构内使用:a = f(1,2)+ g(3,4)”。“不直接在包围结构内”到底是什么意思? 问题答案: 这可能来自PEP 8-Python代码样式指南 。具体来说,请参见“表达式和语句中的空白”部分。 从该部分:

    • 如果有人问起 Python 程序员他们最喜欢 Python 哪一点,他们一定会提到 Python 的高可读性。确实,对于 Python 来说,其高可读性一直是 Python 这门语言设计的核心。一个不争的事实是,相对于写代码而言,读代码才是更加平常的事情。 Python 代码有高可读性的一个原因就是其有着相对而言更加完善的编码风格准则和 「Python化」习语。 当 Python 老手(Pytho

    • 语法 UTF-8编码 Unix换行符,每行120字符 缩进符用4个空格,需要设定编辑器tab转4空格 花括号独占一行 函数与函数间使用一个空行分割 能使用静态内联(static sw_inline)就不要用宏 能用enum枚举就不要用宏 代码可读性比性能更重要 标签 label必须以下划线开头,用于goto语句 label必须独占一行 枚举 命名必须为sw{模块名称}_{作用},如:swServe

    • 这些是 Electron 编码风格指南。 您可以运行 npm run lint 来显示 cpplint 和eslint 检测到的任何样式问题。 通用代码 用换行符结束文件。 按照如下顺序排列 node 模块的 require 代码 内置Node模块(如 path) 内置Electron模块(如 ipc、app) 本地模块(使用相对路径) 按照如下顺序排列类的属性 类方法和属性 (开始于 @ 的方法

    • 良好的编码风格,有助于代码的阅读、调试和修改。虽然 Verilog 代码可以在保证语法正确的前提下任意编写,但是潦草的编码风格往往是一锤子买卖。有时回看自己编写的代码,既看不出信号的意义,也不了解模块的功能,还得从逻辑上一步步分析,就会消耗大量的时间和精力去消化,严重影响设计进度。 为了不让别人或自己由衷的感叹出:这特喵的是哪个"小傻宝"写的代码!下面对编码风格进行一定意义上的建议。 关于命名 信

    • 问题内容: 我是Python的新手,所以如果问题太简单,请不要发火:) 我已经读过Python是从上到下执行的。 如果是这种情况,为什么程序会如下所示: 因此,从我所看到的来看,主要功能最后出现,其他功能堆叠在其顶部。 我说错了吗?如果不是,为什么不从上到下写主函数或函数定义? 编辑:我问为什么我不能这样做: 这不是自然秩序吗?因为它是从上到下执行的,所以您一直在底部添加内容。 问题答案: 该s的