# programming教學 - python reduce

## 計算給定函數改變屬性的對象屬性的“閉包” (2)

``````from collections import deque

def multiply_by_two(x):
return x * 2

def sub_one_div_three(x):
if (x - 1) % 3 == 0:
return (x - 1) // 3
else:
return None # invalid

functions = [multiply_by_two, sub_one_div_three]

# find the path to a given function
def bfs(initial_state, goal):
initial_path = []
states = deque([(initial_state, initial_path)])     # deque of 2-tuples: (state, list of functions to get there)
prev_states = {initial_state}                       # keep track of previously visited states to avoid infinite loop

while states:
# print(list(map(lambda x: x[0], states)))      # print the states, not the paths. useful to see what's going on
state, path = states.popleft()

for func in functions:
new_state = func(state)

if new_state == goal:                       # goal test: if we found the state, we're done
return new_state, path + [func]

if (new_state is not None and           # check that state is valid
new_state not in prev_states):      # and that state hasn't been visited already
states.append((new_state, path + [func]))
else:
raise Exception("Could not get to state")

print(functions)
print(bfs(1, 5))

# prints (5, [<function multiply_by_two at 0x000002E746727F28>, <function multiply_by_two at 0x000002E746727F28>, <function multiply_by_two at 0x000002E746727F28>, <function multiply_by_two at 0x000002E746727F28>, <function sub_one_div_three at 0x000002E7493C9400>]). You can extract the path from here.``````

``````    def func1(obj):
#...

def func2(obj):
#...

def func3(obj):
#...``````

``````obj = MyObject()
obj.attr=22``````

``print closure(obj)``

``````[22, 64, 21, 104] #first path to 104 through , func1(obj),func1(func1(obj)), func1(func1(func3(obj)))

[22, 73, 104] #second path to 104 through , func3(obj),func3(func2(obj)),

[22, 11, 93] #the only path to arrive at 94``````

1. 找出可能的功能組合。

2. 評估可能的功能組合。

``````from itertools import combinations

def comb(fns, n):
return combinations(fns, n)``````

``````def combo_tot(fns):
start=1
while (start <= len(fns)):
for c in comb(fns, start):
yield c
start += 1``````

``````def evalf(fns_to_compose, initval):
v = initval
for fn in fns_to_compose:
v = fn(v)
return v``````

``````def results(fns, init):
return (evalf(fn, init) for fn in combo_tot(fns))``````