我正在编写一个小部件,它可以指定其各个部分的排列方式。
为此,我使用了模块化原理:
“构件块”用于指定任何顺序。
这些“块”被实现为枚举值,其中每个值代表一个单独的组件。
import enum
# The 'blocks'
class E(enum.Enum):
A = 1
B = 2
C = 3
class Test():
def __init__(self, arrangement):
# The passed 'arrangement' is translated into the real arrangement.
real_arrangement = []
for a in arrangement:
if a == E.A:
real_arrangement.append("a_component")
elif a == E.B:
real_arrangement.append("b_component")
elif a == E.C:
real_arrangement.append("c_component")
print(real_arrangement)
# The user can specify an arrangement...
arrangement = (E.A, E.C, E.B)
# ... and pass it to the constructor.
Test(arrangement)
# 'real_arrangement' = ("a_component", "c_component", "b_component")
请注意,占位符已替换,但结构相同。
但是,我也想给元素一些属性一些自由。
因此,除了纯枚举值之外,还可以传递可迭代的变量,其中包含枚举值和其他参数。
# the elements are iterables themself.
arrangement = ((10, E.A),
(20, E.C),
(5, E.B))
# real_arrangement = ((10, "a_component"), (20, "c_component"), (5, "b_component"))
请注意,结构保持不变。
因此,我基本上是尝试克隆一个可迭代的并且递归地替换特定值。
我想到的任何方法都很难理解。
也许已经有我可以使用的解决方案了?
上面的代码在Python 3.5.2上运行。
最佳答案
一种选择是检查arrangement
is iterable的元素,并根据结果使用适当的列表理解。因此,通过一些重构,您可以执行以下操作:
import enum
import collections
# ...
class Test():
def __init__(self, arrangement):
def replace(a):
if a == E.A:
return "a_component"
elif a == E.B:
return "b_component"
elif a == E.C:
return "c_component"
return a
real_arrangement = [tuple(replace(e) for e in a) if isinstance(a, collections.Iterable) else replace(a) for a in arrangement]
print(real_arrangement)
#...
这将使您在问题中发布的两种类型的
arrangement
列表(或“混合”列表)都能正常工作。没有可迭代的元素:
arrangement = (E.A, E.C, E.B)
Test(arrangement)
# ['a_component', 'c_component', 'b_component']
具有所有可迭代的元素:
arrangement = ((10, E.A), (20, E.C), (5, E.B), (1, E.A))
Test(arrangement)
# [(10, 'a_component'), (20, 'c_component'), (5, 'b_component'), (1, 'a_component')]
具有一些可迭代的元素:
arrangement = (E.A, (20, E.C), (5, E.B), (1, E.A))
Test(arrangement)
# ['a_component', (20, 'c_component'), (5, 'b_component'), (1, 'a_component')]