我正在编写一个小部件,可以指定其各个部分的排列方式。
为此,我使用的是模块化原理:
“构件块”用于指定任何顺序。
这些“块”被实现为枚举值,其中每个值代表一个单独的组成部分。
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。上运行的。
答案 0 :(得分:1)
一个选择是检查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')]
答案 1 :(得分:0)
这种方法应该适用于常见的(容器)类。
recursively_replace
函数的参数:
dict
,其中包含以下形式的对:value_to_replace : replacement
。bool
-确定在original
是dict
的情况下是否也应替换密钥。 (默认值为False
。)该函数尝试使用与原始容器相同的容器类。 (不是相同的容器对象。)
def recursively_replace(original, replacements, include_original_keys=False):
"""Clones an iterable and recursively replaces specific values."""
# If this function would be called recursively, the parameters 'replacements' and 'include_original_keys'
# would have to be passed each time. Therefore, a helper function with a reduced parameter list is used
# for the recursion, which nevertheless can access the said parameters.
def _recursion_helper(obj):
#Determine if the object should be replaced. If it is not hashable, the search will throw a TypeError.
try:
if obj in replacements:
return replacements[obj]
except TypeError:
pass
# An iterable is recursively processed depending on its class.
if hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes, bytearray)):
if isinstance(obj, dict):
contents = {}
for key, val in obj.items():
new_key = _recursion_helper(key) if include_original_keys else key
new_val = _recursion_helper(val)
contents[new_key] = new_val
else:
contents = []
for element in obj:
new_element = _recursion_helper(element)
contents.append(new_element)
# Use the same class as the original.
return obj.__class__(contents)
# If it is not replaced and it is not an iterable, return it.
return obj
return _recursion_helper(original)
# Demonstration
if __name__ == "__main__":
import enum
# Define an enumeration whose values should be replaced later.
class E(enum.Enum):
A = 1
B = 2
C = 3
# Map the values to be replaced with their respective replacements.
dict_with_replacements = {E.A : "a_replacement",
E.B : "b_replacement",
E.C : "c_replacement"}
### example 1 ###
test = (E.A, E.C, E.B)
result = recursively_replace(test, dict_with_replacements)
print(result) # ('a_component', 'c_component', 'b_component')
### example 2 ###
test = ((10, E.A), (20, E.C), (5, E.B))
result = recursively_replace(test, dict_with_replacements)
print(result) # ((10, 'a_component'), (20, 'c_component'), (5, 'b_component'))
### example 3 ###
test = (E.A, (20, E.C), (5, E.B))
result = recursively_replace(test, dict_with_replacements)
print(result) # ('a_component', (20, 'c_component'), (5, 'b_component'))
### example 4 & 5 ###
test = (E.A, {20:E.C, E.B:5})
result = recursively_replace(test, dict_with_replacements)
print(result) # ('a_component', {<E.B: 2>: 5, 20: 'c_component'})
result = recursively_replace(test, dict_with_replacements, True)
print(result) # ('a_component', {'b_component': 5, 20: 'c_component'})