4

免责声明:您好所有 Python 大师和粉丝。我要感谢大家的关心支持和宝贵的建议,这对我帮助很大。我是一名 Python 新手,正在努力学习和进步,同时牢记最佳实践的重要性。这是一个问题,我正在寻找一种快速的方法来避免类型检查,就好像我在这里学到了一件事,这不是一件好事,必须有另一种方法来做。

我正在构建一个数据对象来表示站点地图。我希望它在内存中,这样我就可以在查询数据库之前快速映射 URL。

每个节点必须有 2 个元素。一个(网站部分的)名称和一个ID(它在 DB 中的 ID)(通常为 4 到 8 位数字,但这里仅用一位数字表示)。

如果此节点有子节点(在页面上),则它具有名称、ID和另一个代表子节点的字典

出于性能、易于迭代和记忆的原因,我决定使用以下内容: 我过去尝试只列出 [name, id, [name, id, ..]],字典,我认为这不是这样的不好的方式。

sitemap = {'section_one': 0,
           'section_two': [1, {'c_sect_2_1': 10,
                         'c_sect_2_2': [11, {'c_sect_2_2_1': 110,
                                           'c_sect_2_2_2': 111,
                                           'c_sect_2_2_3': 112}],
                          'c_sect_2_3': 12,
                          'c_sect_2_4': 13}],
           'section_three': 2,
           'section_four': 3,
           'section_five': 4}

我选择列表是因为我可能需要修改它们(因此没有元组) 我正在使用字典(可散列)并且我可以轻松检查它们是否包含一个部分。

使用这个数据集和下面的函数,我映射一个 URL(例如 /section_two/c_sect_2_2/c_sect_2_2_3)并查看它是否存在以从数据库中获取数据。我的功能:

def map_url(url): #url here is a list e.g. ['section_two', 'c_sect_2_2', 'c_sect_2_2_3']
    sm = sitemap
    for e in url:
        if e in sm:
            if isinstance(sm[e], int):
                return sm[e] #e = where it stops matching due to no children
            sm = sm[e][1] #if not INT it's a list. list[1] has another dict to go-through
    return False #the URL could not be matched-mapped

我的问题是:

  1. 而不是检查字典中项目的值是否是整数来查看它是否有孩子,我应该怎么做?我能做些什么?
  2. 什么可能是整个事情的替代品?(数据结构的构建方式和/或通过它的迭代)

我需要这种 url 映射方式,因为我的网站可以有很多嵌套的部分,我不想多次查询数据库来查看它是否存在。

最后,感谢大家宝贵的时间和建议。

4

3 回答 3

6

而不是检查字典中项目的值是否是整数来查看它是否有孩子,我应该怎么做?我能做些什么?

问题似乎是您对有孩子的部分和没有孩子的部分使用了不同的表示形式。没有孩子的部分实际上应该只是一个包含空子列表的部分:

sitemap = {'section_one': [0, {}],
           'section_two': [1, {'c_sect_2_1': [10, {}],
                               'c_sect_2_2': [11, {'c_sect_2_2_1': [110, {}],
                                                   'c_sect_2_2_2': [111, {}],
                                                   'c_sect_2_2_3': [112, {}]}],
                               'c_sect_2_3': [12, {}],
                               'c_sect_2_4': [13, {}]}],
           'section_three': [2, {}],
           'section_four': [3, {}],
           'section_five': [4, {}]}

现在你的代码应该变得更简单了。

什么可能是整个事情的替代品?(数据结构的构建方式和/或通过它的迭代)

您可以在程序开始时将站点地图转换为平面字典,使其类似于

flat_sitemap = { 
    'section_one': 0,
    'section_two': 1,
    'section_two/c_sect_2_1': 10,
       # ...
    'section_two/c_sect_2_2/c_sect_2_2_1': 110
       # ...
    }

这样,您的查询将以O(1)更高的空间使用为代价在预期的时间内工作。

至于以不同的方式处理原始结构,您可以使用递归。我经常发现以递归方式在树状结构上制定算法更容易,但这有点取决于你的思维方式。这是一个示例(我假设其格式sitemap显示在我的第一个示例中):

def map_url(url, sm=[None, sitemap]):
    if not url: return sm[0]
    if url[0] not in sm[1]: return False
    return map_url(url[1:], sm[1][url[0]])

print map_url(['section_two', 'c_sect_2_2', 'c_sect_2_2_3']) # => 112
print map_url(['section_two', 'c_sect_2_2'])                 # => 10
print map_url(['section_two', 'notexisting'])                # => False
print map_url([])                                            # => None

如您所见,这使得传递空 URL 的特殊情况变得明确。您绝对应该考虑在这种特殊情况下应该发生什么。

你甚至可以离开函数的第二行。在这种情况下,KeyError如果无法匹配 URL,则会抛出 a(这似乎也很合理)。

于 2012-08-19T14:57:19.180 回答
4

更一致的方法是始终使用 id 和 dict 的组合,但如果没有孩子,则使用空 dict。

sitemap = {'section_one': [0, {}],
           'section_two': [1, {'c_sect_2_1': [10,{}],
                         'c_sect_2_2': [11, {'c_sect_2_2_1': [110,{}],
                                           'c_sect_2_2_2': [111,{}],
                                           'c_sect_2_2_3': [112,{}]}],
                          'c_sect_2_3': [12,{}],
                          'c_sect_2_4': [0,{}]}],
           'section_three':[2,{}],
           'section_four': [3,{}],
           'section_five': [4,{}]}

这样你就可以随时检查剩余的 url 部分是否在子字典中。

于 2012-08-19T14:57:19.773 回答
0

对于您的第一个问题:pythonic 方法不是检查类型,而是尝试捕获异常:

sm = sitemap
for e in url:
    if e in sm:
        try:
            sm = sm[e][1]
        except TypeError:
            return sm[e]
return False 

在这里,如果sm[e]是一个整数,它不能被索引并TypeError引发异常:然后您可以返回您的项目。如果sm[e]可以被索引,则更新您的sm. 如果索引失败(例如,因为只有一个元素),则会引发另一个您也可以捕获的异常。

于 2012-08-19T14:52:57.177 回答