将变量传递给某些if语句(共享范围)



考虑以下代码:

def function(condition):
if condition == 'condition1':
print('No problem here')
if condition == 'condition2':
test = ['1','2','3','4']
print(test)
if condition == 'condition3':
#doing something else using variable 'test'

是否可以在两个if语句之间共享静态列表?目前,我有两个可行的想法,但都有其局限性

情况1:在函数的开头声明静态列表

def function(condition):
test = ['1','2','3','4']
if condition == 'condition1':
print('No problem here')
if condition == 'condition2':
print(test)
if condition == 'condition3':
#doing something else using variable 'test'

限制:这意味着我每次调用function时都会创建列表,即使condition == 'condition1'时我不需要它

情况2:在两个if语句中声明静态列表

def function(condition):
if condition == 'condition1':
print('No problem here')
if condition == 'condition2':
test = ['1','2','3','4']
print(test)
if condition == 'condition3':
test = ['1','2','3','4']
#doing something else using variable 'test'

限制:在这种特殊情况下,情况似乎没有那么糟糕,但如果我的列表中有更多嵌套列表的数据,重复它会使代码维护更加困难,因为需要多次进行更改。

也许有一个简单的方法可以解决这个问题,我想得太多了,但正如我所说,这是我第一次看到这种情况。

创建这个列表很简单。您在发布问题上花费的资源可能比使用最佳解决方案节省的资源还多。:-)如果每个函数调用的列表都相同,那么您有几个好的选择:

(1) 您的案例1很好:它易于阅读和维护。如果你担心赋值,打开优化开关,让解释器意识到这是一个常量赋值。

(2) 强制自己保持常量状态:将赋值放在函数之前。

test = ['1','2','3','4']
def function(condition):
if condition ...

编辑

有关更多信息,请参阅此答案中的时间

在调用lambda之前,不会计算lambda表达式的右侧。如果你想避免重新计算列表,你可以

def function(condition):
getTestArray = lambda: ['1','2','3','4']
if condition == 'condition1':
print('No problem here')
if condition == 'condition2':
test = getTestArray()
print(test)
if condition == 'condition3':
test = getTestArray()
#doing something else using variable 'test'

当我们讨论这个主题时,我应该提到Python的lambda及其BDFL Guido有着有趣的历史:https://www.quora.com/Why-did-Guido-van-Rossum-want-to-remove-lambda-from-Python-3/answer/Max-Fischer-10

我讨厌条件句。使用对象和多态性。这可能看起来像是更多的前期工作,但这种模式非常强大,值得学习:

class ProblemAbstract:
@property
def test_data(self):
return [1, 2, 3, 4]
def process(self):
raise NotImplementedError("Need to implement 'process'")

class NullProblem(ProblemAbstract):
def process(self):
return None

class ProblemType1(ProblemAbstract):
def process(self):
return "Do something with: {}".format(self.test_data)

class ProblemType2(ProblemAbstract):
def process(self):
return "Do something else with: {}".format(self.test_data)

def function(condition):
condition_matrix = {
'condition1': NullProblem,
'condition2': ProblemType1,
'condition3': ProblemType2,
}
return condition_matrix[condition]().process()
if __name__ == "__main__":
print(function('condition1'))
print(function('condition2'))
print(function('condition3'))

输出:

None
Do something with: [1, 2, 3, 4]
Do something else with: [1, 2, 3, 4]

我最终使用了@wvxvw的注释中的解决方案,道具交给了他。

我决定创建一个类似的函数

def get_test():
test = ['1','2','3','4']
return test
def function(condition):
if condition == 'condition1':
print('No problem here')
if condition == 'condition2':
test = get_test()
print(test)
if condition == 'condition3':
test= get_test()

其他答案都很好,但我并不总是同意选择不优化代码是最好的做法。也许我错了,这是针对个人的,但上面显示的代码在我看来是优化的、可读的和可维护的。特别是对于function将被调用数千次的情况。

编辑

我把握了一些时间来确认答案。这是一个使用的代码示例,这是我所说的Case1

import time
def function(condition):
test = ['1','2','3','4']
if condition == 'condition1':
pass
if condition == 'condition2':
pass
if condition == 'condition3':
pass
start_time = time.time()
num_iterations = 10000
for i in range(num_iterations):
function('condition1')
function('condition2')
function('condition3')
print("Case1 for %d iterations" %(num_iterations))    
print("--- %s seconds ---" % (time.time() - start_time))

我对案例2遵循了相同的模式,这与我的问题中的病例2件3代表我回答中使用的逻辑。正如您所看到的,只有列表创建会影响测试的时间。

结果

Case1 for 10000 iterations
--- 0.01559591293334961 seconds ---
Case2 for 10000 iterations
--- 0.015594244003295898 seconds ---
Case3 for 10000 iterations
--- 0.015636682510375977 seconds ---
Case1 for 1000000 iterations
--- 1.1179990768432617 seconds ---
Case2 for 1000000 iterations
--- 0.9396021366119385 seconds ---
Case3 for 1000000 iterations
--- 1.0606272220611572 seconds ---

摘要

我们可以得出结论,所有的方法都是相同的,以实现效率。尽管对于纯性能,Case2似乎是最好的(仔细想想,这是合乎逻辑的)。不过,我认为我们应该参考这个答案。

类似@RobertB答案,但使用函数式编程:

from functools import partial
def condition1():
print('Hello first case')
def condition2(test):
print('Hello second case. Test var is: {0}'.format(test))
def condition3(test):
print('Hello thrid case. Test var is: {0}'.format(test))
def function(condition):
test = []
if condition in ('condition2', 'condition3'):
test = ['1','2','3','4']
conditions = {
'condition1': condition1,
'condition2': partial(condition2, test),
'condition3': partial(condition3, test)
}
action = conditions.get(condition, lambda: print(NotImplemented))
action()
function('condition')
function('condition1')
function('condition2')
function('condition3')

最新更新