python - 给定改变属性的函数计算对象属性的 "closure"

标签 python oop object functional-programming state

我有一个对象 obj 和一些函数

    def func1(obj):
    #...

    def func2(obj):
    #...

    def func3(obj):
    #...

每次更改obj 的属性值。

我希望我的输入是这样的

obj = MyObject()
obj.attr=22

这应该传递给一个函数closure(),它计算上述函数的所有可能的应用,意思是func1(func2(obj)), func3 (func1(func1(obj))) 等直到某个停止条件(例如不超过 20 个函数组合)。

输出应该是所有可能输出的列表以及通往那里的所有路径。因此,假设 10493obj.attr=22 的可能最终输出,并且有两种方法可以到达 104 和一个到达 93。然后

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

我该如何实现?正如评论中所建议的那样,最好用树来完成,但是尽管我尝试了 2 天,但我几乎没有在实现它方面取得任何进展(我是 Python/编程的新手)!
我的示例非常简单,我们可以直接使用 func(22) 而不是 func(obj) 但我需要处理的示例更复杂,我肯定会需要使用对象,因此这只是一个最小的工作示例。

这棵树可能不是完整的 n 叉树,因为每个函数应用程序都包含一个测试,它是否可以应用于 obj 的当前状态(属性的),并且在某些情况下在测试失败的情况下,obj 的(属性)保持不变。

最佳答案

这是一个简单的例子,它试图找出一个数字 (goal) 是否是前导数 在应用 Collatz conjecture 中的规则时另一个 (inital_state) .

在您的示例中,obj状态[func1, func2, ...]函数 在我的例子中。 此版本将返回最终输出的路径,从而最大限度地减少函数应用程序的数量。 您可以通过删除目标测试并在循环完成后返回 prev_states 来列出所有状态,而不是搜索。

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]))
            prev_states.add(new_state)              # make sure state won't be added again
    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.

关于python - 给定改变属性的函数计算对象属性的 "closure",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46176179/

相关文章:

java - 注册对象字段值 Java

php - 转换 Javascript 关联对象并在 PHP 中输​​出

python - 如何按属性访问列表中的对象?

c# - Object.GetHashCode() 的实现

python - 从 Celery 任务使用 SocketIO 推送服务器

python - 间距不规则的条形图

c# - 如何跳过类中接口(interface)的实现

c# - 在 C# 中编程为父类(super class)型

python - 如何嵌套任意数量的 Python 文件上下文管理器?

java - ZeroTurnaround Process Executor (zt-exec) 进程在无限循环中等待输入,如何?