Python - 编码风格 - 跨函数更改多个变量

时间:2017-09-30 15:39:51

标签: python python-3.x function variables global-variables

问题:一个功能是读取配置文件并按比例设置许多变量。 其他几个函数需要其中几个变量来完成这项任务。

最佳实践说,全局变量是不行的,所以我在考虑改变/使用非函数本地变量的改变 当有很多变量需要处理时?

第一个是明显的变量转移到函数并正常返回结果。

第二种方法是直接更改/使用变量,但这是一种可接受的python方式,或者只是其他方式"全局变量?

第三种方法是将所有变量放入列表中并在函数中使用该列表...

哪种方法适合在Python3中使用(如果一种方法比其他方法更好),哪种方法应该避免(如果有的话)?

是的,我确信还有其他几种方法可以做到,我现在还不知道这些方法: - )

e.g。 #1)

def do_something(a, b, c, d, e):
    print(a, b, c, d, e)
    a = 'new1'
    b = 'new2'
    c = 'new3'
    d = 'new4'
    e = 'new5'
    return (a, b, c, d, e)

def main():
    var1 = 'test1'
    var2 = 'test2'
    var3 = 'test3'
    var4 = 'test4'
    var5 = 'test5'
    print(var1, var2, var3, var4, var5)
    var1, var2, var3, var4, var5 = do_something(var1, var2, var3, var4, var5)
    print(var1, var2, var3, var4, var5)

if __name__ == '__main__':
    main()

e.g。 #2)

def do_something():
    print(main.var1, main.var2, main.var3, main.var4, main.var5)
    main.var1 = 'new1'
    main.var2 = 'new2'
    main.var3 = 'new3'
    main.var4 = 'new4'
    main.var5 = 'new5'

def main():
    main.var1 = 'test1'
    main.var2 = 'test2'
    main.var3 = 'test3'
    main.var4 = 'test4'
    main.var5 = 'test5'
    print(main.var1, main.var2, main.var3, main.var4, main.var5)
    do_something()
    print(main.var1, main.var2, main.var3, main.var4, main.var5)

if __name__ == '__main__':
    main()

e.g。 #3)

def do_something_list(li):
    print(li)
    li[0] = 'new1'
    li[1] = 'new2'
    li[2] = 'new3'
    li[3] = 'new4'
    li[4] = 'new5'
    return (li)

def main():
    var1 = 'test1'
    var2 = 'test2'
    var3 = 'test3'
    var4 = 'test4'
    var5 = 'test5'
    list1 = [var1, var2, var3, var4, var5]
    print(list1)
    list1 = do_something_list(list1)
    print(list1)

if __name__ == '__main__':
    main()

2 个答案:

答案 0 :(得分:0)

简短回答:没有通用解决方案。每个问题都需要基于专业和平衡的个人方法。针对该特定用例的缺点。你的用例是什么?

最好的方法和最常用的方法是使用容器对象,例如" config",并将其传递给所需的每个功能。然后,您可以将这些变量作为config.myfield(如果它支持字段访问)或config['myfield']或以类似​​方式访问。

然而,这也不是最好的解决方案。但是比较简单。特别是当您需要将值(例如配置)从顶级(例如,CLI解析器,配置解析器)传递到非常低级别的功能(例如,Web请求处理)时。

有时,在更大的框架中,此配置/容器对象附加到每个调用实体(例如,Web框架中的Web request);或作为全局对象提供(例如,pytest中的request.config);或类似的东西。

在这种情况下,框架负责以这种或那种方式将容器对象传递到您的函数中。他们还可以通过将这些对象保存在每线程内存中来确保这些对象是线程安全的。并且对象是不可变的(即,如果一个请求修改它,所有并行或进一步的请求将不会看到更改)。

特别是在你的例子中,它们都很糟糕(很遗憾地说)。

示例#1修改了函数局部变量,这些变量在所有其他函数中都不可见;如果你声明它们global,它们将是模块范围的。

示例#2将字段分配给函数对象(sic!)。而且你必须将main函数作为配置对象传递(坏主意)。

示例#3可行,但不方便:您必须记住每个值的位置;如上所述,将其转换为具有任意字段的dict或配置对象将执行操作。

答案 1 :(得分:0)

使用全局变量是正确的,这不是做这样的事情的最好方法。一般来说,最佳实践是你在例子1中所做的。然而,在python中,当你在传递var的函数内部更改变量时,需要注意一些事项。

def func1(list1, string1):
    list1.append('in func1')
    string1 = 'in func1 string'


def main():
    list1 = ['in main']
    string1 = 'main string'
    func1(list1, string1)
    print list1
    print string1

输出:

['in main', 'in func1']
main string

根据传递给函数的变量类型以及使用它执行的操作,您可以无意中更改父函数中的值。

经验法则是,如果传递的var的类型是immutable type(int,float,decimal,complex,bool,string,tuple,range,frozenset,bytes),则无法更改初始变量值除了返回具有新值的新变量之外。在这种情况下,如果要返回不同的值,最佳做法是在子函数内使用不同的变量名。

如果变量是mutable type(list,dict,set,bytearray,用户定义的类(除非特别设为不可变)),最佳做法是不更改子函数中的变量值,而是更改复制该值并返回具有更改值的新变量。

from copy import deepcopy

def func1(list1):
    new_list = deepcopy(list1)
    new_list.append('in func1')
    return new_list


def main():
    list1 = ['in main']
    new_func_list = func1(list1)
    print list1
    print new_func_list

输出:

['in main']
['in main', 'in func1']

现在,在更改子函数中的可变对象时,可能会遇到一个更大的陷阱。

def func1(list1):
    new_list = list1
    new_list.append('in func1')


def main():
    list1 = ['in main']
    func1(list1)
    print list1

输出:

['in main', 'in func1']

即使将可变变量重新分配给新变量,新变量仍然指向(意味着您将要编辑)与原始变量相同的值。