我有一个包含iterables的python字典,其中一些是列表,但大多数是其他字典.我想做类似以下的glob-style赋值:
myiter['*']['*.txt']['name'] = 'Woot'
Run Code Online (Sandbox Code Playgroud)
也就是说,对于myiter中的每个元素,使用以".txt"结尾的键查找所有元素,然后将"name"项设置为"Woot".
我已经考虑过对dict进行子类化和使用fnmatch模块.但是,我不清楚实现这一目标的最佳方法是什么.
我认为最好的方法是不要这样做——'*'它是字典中完全有效的键,因此myiter['*']具有完全明确定义的含义和有用性,并且颠覆肯定会导致问题。如何“通配”非字符串的键,包括列表而非映射元素中的唯一整数“键”(索引),也是一个设计问题。
如果您仍然必须这样做,我建议通过子类化抽象基类来完全控制,并 实现collections.MutableMapping所需的方法(、、、、、、,__len__并且为了获得更好的性能,还重写其他方法,例如ABC 确实在其他的基础,但缓慢)就包含而言。相反,根据其他建议,子类化将要求您覆盖大量方法,以避免在您覆盖的方法和不覆盖的方法中使用“包含通配符的键”之间出现不一致的行为。__iter____getitem____setitem____delitem____contains__dictdict
无论是子类化collections.MutableMapping,还是dict,为了创建您的Globbable类,您都必须做出核心设计决策:当a时yourthing[somekey] 返回什么?yourthingGlobbable
somekey据推测,当是 包含通配符的字符串时,它必须返回不同的类型,而不是其他类型。在后一种情况下,人们会想象该条目实际上是什么;但在前者中,它不能只返回另一个Globbable- 否则,在一般情况下会yourthing[somekey] = 'bah' 做什么?对于您的单个“光滑语法”示例,您希望它somekey在每个项目中设置一个条目yourthing(与宇宙中每个其他映射的行为存在巨大的语义中断;-)——但是,您将如何设置本身就是一个条目yourthing?!
让我们看看 Python 之禅是否对您渴望的这种“圆滑语法”有什么话要说……:
>>> import this
...
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Run Code Online (Sandbox Code Playgroud)
考虑一下放弃“圆滑的语法”(以及它必然暗示的所有巨大的语义头痛)的替代方案,以支持清晰和简单(此处使用 Python 2.7 和更好的语法,只是为了字典理解 - 使用dict(...)如果您坚持使用 2.6 或更早版本,请改为显式调用),例如:
def match(s, pat):
try: return fnmatch.fnmatch(s, pat)
except TypeError: return False
def sel(ds, pat):
return [d[k] for d in ds for k in d if match(k, pat)]
def set(ds, k, v):
for d in ds: d[k] = v
Run Code Online (Sandbox Code Playgroud)
所以你的作业可能会变成
set(sel(sel([myiter], '*')), '*.txt'), 'name', 'Woot')
Run Code Online (Sandbox Code Playgroud)
(如果所有的选择'*'都是多余的,我只是省略它)。这是否如此可怕以至于值得我上面提到的问题泥沼来代替使用
myiter['*']['*.txt']['name'] = 'Woot'
Run Code Online (Sandbox Code Playgroud)
...?当然,到目前为止,最清晰、效果最好的方法仍然是更简单的方法
def match(k, v, pat):
try:
if fnmatch.fnmatch(k, pat):
return isinstance(v, dict)
except TypeError:
return False
for k, v in myiter.items():
if match(k, v, '*'):
for sk, sv in v.items():
if match(sk, sv, '*.txt'):
sv['name'] = 'Woot'
Run Code Online (Sandbox Code Playgroud)
但如果你绝对渴望简洁和紧凑,鄙视Python的禅宗公案“稀疏胜于密集”,那么你至少可以获得它们,而不必经历我所提到的实现你理想的“语法糖”所需的各种噩梦。
| 归档时间: |
|
| 查看次数: |
1390 次 |
| 最近记录: |