类中递归函数的静态方法?

时间:2018-07-05 18:20:58

标签: python python-2.7

我正在使用从YAML对象获得的Python(2.7)上的嵌套字典,我有几个问题一直在尝试通过阅读获得答案,但没有成功。我对Python有点陌生。

最简单的功能之一是读取整个字典并输出其中存在的所有键的列表。我一开始使用下划线,因为此功能稍后将由班级中的其他人使用。

    class Myclass(object):

    @staticmethod
    def _get_key_list(d,keylist):
        for key,value in d.iteritems():
            keylist.append(key)
            if isinstance(value,dict):
                Myclass._get_key_list(d.get(key),keylist)
        return list(set(keylist))

    def diff(self,dict2):
        keylist = []
        all_keys1 = self._get_key_list(self.d,keylist)
        all_keys2 = self._get_key_list(dict2,keylist)
        ... # More code

问题1:这是这样做的正确方法吗?因此,我不确定使用静态方法是否是一种好习惯。由于self._get_key_list(d,keylist)是递归的,因此我不希望在递归调用函数后将“自我”作为第一个参数,这对于常规实例方法将是这种情况。

我有很多静态方法正在使用,但是我在很多地方都读过,所以经常使用它们可能不是一个好习惯。我还认为我可以使它们成为模块函数,但我希望它们与类联系在一起。

问题2:如何将参数keylist传递给self._get_key_list(d,keylist),而不是如何在递归函数中初始化一个空列表并进行更新?在内部对其进行初始化会每次将其重置为[]。

2 个答案:

答案 0 :(得分:1)

我将消除keylist作为显式参数:

def _get_keys(d):
    keyset = set()
    for key, value in d.iteritems():
        keylist.add(key)
        if isinstance(value, dict):
            keylist.update(_get_key_list(value))
    return keyset

如果呼叫者确实需要列表而不是可迭代的,则让呼叫者将其转换为列表。

通常,没有理由将某些东西声明为静态方法而不是类外部的函数。

如果您担心效率(例如,从字典中获取很多重复键),则可以返回通过调用将单个集合/列表作为显式参数进行线程化,但不要使其成为可选参数;仅要求初始呼叫者提供要更新的设置/列表。为了强调第二个参数将被突变,只需在函数返回时返回None

def _get_keys(d, result):
    for key, value in d.iteritems():
        result.add(key)
        if isinstance(value, dict):
            _get_keys(value, result)

result = set()
_get_keys(d1, result)
_get_keys(d2, result)
# etc

答案 1 :(得分:0)

没有充分的理由将类中的递归函数设为静态方法,除非要在实例的上下文之外调用它。

要初始化参数,我们通常在参数列表中为其分配一个默认值,但是如果该参数需要是可变对象(例如在这种情况下为空列表),则需要将其默认设置为None并进行初始化它放在函数中,这样列表引用就不会在下一次调用中重用:

class Myclass(object):
    def _get_key_list(self, d, keylist=None):
        if keylist is None:
            keylist = []
        for key, value in d.iteritems():
            keylist.append(key)
            if isinstance(value, dict):
                self._get_key_list(d.get(key), keylist)
        return list(set(keylist))

    def diff(self, dict2):
        all_keys1 = self._get_key_list(self.d)
        all_keys2 = self._get_key_list(dict2)
        ...  # More code