如何为一个伟大的元素而奋斗

2024-10-03 19:24:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含iterable的python字典,其中一些是列表,但大多数是其他字典。我想做类似于以下内容的全局式作业:

myiter['*']['*.txt']['name'] = 'Woot'

也就是说,对于myiter中的每个元素,查找键以“.txt”结尾的所有元素,然后将它们的“name”项设置为“Woot”。在

我考虑过对dict进行子分类并使用fnmatch模块。但是,我不清楚实现这一目标的最佳方式是什么。在


Tags: 模块nametxt元素列表字典结尾分类
3条回答

最好的方法是将dict子类化并使用fnmatch模块。在

  • 子类dict:以面向对象的方式添加所需的功能。在
  • fnmatch模块:重用现有功能。在

我认为,最好的方法是而不是这样做-'*'是dict中一个完全有效的键,因此myiter['*']有一个定义明确的含义和有用性,颠覆肯定会引起问题。如何“glob”在不是字符串的键上,包括列表而不是映射的元素中的独占整数“键”(索引),也是一个相当大的设计问题。在

如果您仍然必须这样做,我建议您通过将abstract base classcollections.MutableMapping子类化来实现完全控制,实现所需的方法(__len____iter____getitem____setitem____delitem__,为了获得更好的性能,还可以覆盖其他方法,如__contains__,ABC确实在其他方法的基础上实现这些方法,但是慢慢地)就包含的dict而言。相反,根据其他建议,子类化dict将需要重写大量方法,以避免在重写的方法中使用“包含通配符的键”与不重写的方法之间的不一致行为

无论您是子类collections.MutableMapping,还是dict,要生成您的Globbable类,您必须做出一个核心设计决策:当yourthingGlobbable时,yourthing[somekey]返回的是什么?在

somekey是一个包含通配符的字符串时,它可能必须返回不同的类型,而不是其他类型。在后一种情况下,我们可以想象,在该条目中实际是什么;但是在前一种情况下,它不能仅仅返回另一个Globbable——否则,在一般情况下,yourthing[somekey] = 'bah'会做什么?对于您的单个“slick syntax”示例,您希望它在yourthing的每个项中设置一个somekey项(一个巨大的语义与宇宙中其他映射的行为相分离;—)——但是,那么,您如何在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.

暂时考虑一下另一种选择,即放弃“流畅的语法”(以及它必然意味着的所有巨大的语义上的麻烦)而倾向于清晰和简单(这里使用Python2.7和更好的语法,只是为了理解dict——如果您坚持使用2.6或更早版本,请使用显式的dict(...)调用),例如:

^{pr2}$

所以你的任务可能变成

^{3}$

(带有'*'的选择是多余的,我只是省略它)。这是不是太可怕了,值得我在上面提到的一大堆问题来代替它

myiter['*']['*.txt']['name'] = 'Woot'

。。。?当然,到目前为止,最清晰和最好的执行方式仍然是更简单的

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'

但是如果你绝对渴望简洁和紧凑,轻视Python的koan“稀疏胜于密集”的禅意,你至少可以不必做我提到的各种噩梦来实现你理想的“语法糖”。在

您可以使用^{}作为匹配字典键的功能,但是您必须稍微妥协语法,特别是如果您想在嵌套字典上这样做的话。也许一个自定义的类似字典的类带有返回通配符匹配的搜索方法会很好地工作。在

下面是一个非常基本的示例,它带有一个警告:这不是递归的,并且不会处理嵌套字典:

from fnmatch import fnmatch

class GlobDict(dict):
    def glob(self, match):
        """@match should be a glob style pattern match (e.g. '*.txt')"""
        return dict([(k,v) for k,v  in self.items() if fnmatch(k, match)])

# Start with a basic dict
basic_dict = {'file1.jpg':'image', 'file2.txt':'text', 'file3.mpg':'movie',
              'file4.txt':'text'}

# Create a GlobDict from it
glob_dict = GlobDict( **basic_dict )

# Then get glob-styl results!
globbed_results = glob_dict.glob('*.txt')
# => {'file4.txt': 'text', 'file2.txt': 'text'}

至于什么方法是最好的?最好的方法是有效的方法。不要试图在解决方案创建之前优化它!在

相关问题 更多 >