通过将代码片段打包到函数中,程序可以更具声明性。
- from random import random
-
- def move_cars():
- for i, _ in enumerate(car_positions):
- if random() > 0.3:
- car_positions[i] += 1
-
- def draw_car(car_position):
- print '-' * car_position
-
- def run_step_of_race():
- global time
- time -= 1
- move_cars()
-
- def draw():
- print ''
- for car_position in car_positions:
- draw_car(car_position)
-
- time = 5
- car_positions = [1, 1, 1]
-
- while time:
- run_step_of_race()
- draw()
要理解这个程序,读者只需读一下主循环。『如果还剩下时间,请跑一步,然后画出线图。再次检查时间。』如果读者想要了解更多关于比赛步骤或画图的含义,可以阅读对应函数的代码。
没什么要再说明的了。 代码是自描述的。
拆分代码成函数是一种很好的、简单易行的方法,能使代码更具可读性。
这个技术使用函数,但将函数用作子例程( sub-routine ),用于打包代码。对照上文说的指南针,这样的代码并不是函数式的。实现中的函数使用了没有作为参数传递的状态,即通过更改外部变量而不是返回值来影响函数周围的代码。要确认函数真正做了什么,读者必须仔细阅读每一行。如果找到一个外部变量,必须反查它的源头,并检查其他哪些函数更改了这个变量。
消除状态
下面是赛车代码的函数式版本:
- from random import random
-
- def move_cars(car_positions):
- return map(lambda x: x + 1 if random() > 0.3 else x,
- car_positions)
-
- def output_car(car_position):
- return '-' * car_position
-
- def run_step_of_race(state):
- return {'time': state['time'] - 1,
- 'car_positions': move_cars(state['car_positions'])}
-
- def draw(state):
- print ''
- print 'n'.join(map(output_car, state['car_positions']))
-
- def race(state):
- draw(state)
- if state['time']:
- race(run_step_of_race(state))
-
- race({'time': 5,
- 'car_positions': [1, 1, 1]})
代码仍然是分解成函数。但这些函数是函数式的,有三个迹象表明这点:
- 不再有任何共享变量。
time 与 car_position 作为参数传入 race() 。
- 函数是有参数的。
- 在函数内部没有变量实例化。所有数据更改都使用返回值完成。基于
run_step_of_race() 的结果, race() 做递归调用。每当一个步骤生成一个新状态时,立即传递到下一步。
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|