performance - Python Coding Style Dilemma -
there several known python code style rules, considered default , try adhere:
wrap lines don’t exceed 79 characters.
keep indents 4 spaces long.
another common programming advice is
avoid global variables
in other words, 1 should use functions accept variables parameters , avoid pascal-like procedures read directly higher scope.
however, in cases, 1 should break of these rules. example, if functions long parameters lists involved. there 2 separate issues them:
first, in heavily indented blocks there little room left.
def function(variable1, variable2, variable3, variable4, variable5,\ variable6, variable7, variable8, variable9): return variable1 + variable2 + variable3 + variable4 + variable5 +\ variable6 + variable7 + variable8 + variable9 def... variable1... if variable 2... while variable3... if variable4... variable5... ... variable10 =\ function(\ variable1,\ variable2,\ variable3,\ variable4,\ variable5,\ variable6,\ variable7,\ variable8,\ variable9) ...
here procedure closure, though considered bad practice, can become helpful:
def... def procedure(): variable10 = variable1 + variable2 + variable3 + variable4 +\ variable5 + variable6 + variable7 + variable8 + variable9 variable1... if variable 2... while variable3... if variable4... variable5... ... procedure() ...
another issue (which python-specific) performance. copying of function parameters can become quite costly if there lot of them:
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() 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() in range(10000000): procedure() finishtime = time.time() print('procedure runtime: {:.3f} s'.format(finishtime - start time))
this outputs:
classical function runtime: 2.447 s procedure runtime: 1.180 s
therefore, question, directed experienced developers, is:
is there can justify use of pascal-like procedures on classical functions or should avoided @ cost, if lead bulkier , slower code?
edit:
using *args
, **kwargs
solves issue partially, parameters still have listed during function call. not address performance issue, parameters still getting copied. itertools
, proposed in comments, not applicable. in cases, resolving nesting quite tricky (consider code below) , take lot of developing time, leading tangled code.
def my_function(**kwargs): open(kwargs['file_a'], 'r') input1: line1 in input1: if kwargs['number'] % 3 == 0: if kwargs['number'] % 9 == 0: open(kwargs['file_0'], 'r') input2: line2 in input2: if line1.startswith('#'): if line2.startswith('a'): open('output.txt') output1: item in kwargs['items']: if item in kwargs['good']: 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 , 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: open(kwargs['file_1'], 'r') input2: ... elif kwargs['number'] % 3 == 2: open(kwargs['file_2'], 'r') input2: ...
someone mentioned in comments: try using
itertools.product()
if have 2 or more nested loops.if above can't done, atleast can reduce indent levels caused
if
statements. example:for abc in .. if (condition): xyz in ...
can changed to:
for abc in ... if not (condition): continue xyz in ...
if there many parameters passed method, try using
*args
(all parameters in tuple) or**kwargs
(all parameters in dict).
edit: per specific requirement, have edited given code. might not produce exact same result yours, give general idea how implement above 3 points.
def my_function(**kwargs): process_var_list = ['var1', 'var2', 'var3', 'var4', 'var5', 'var6', 'var7', 'var8', 'var9', 'var10'] #open 3 files @ 1 go. improve performance , reduce nested loops open(kwargs['file_a'], 'r') input1, open(kwargs['file_0'], 'r') input2, open('output.txt') output1: #following point 1 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']: sub in item: if sub < 0: var_args = {var: kwargs[var] 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: open(kwargs['file_1'], 'r') input2: pass elif kwargs['number'] % 3 == 2: open(kwargs['file_2'], 'r') input2: pass
Comments
Post a Comment