Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类中递归函数的静态方法?_Python_Python 2.7 - Fatal编程技术网

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

Python 类中递归函数的静态方法?,python,python-2.7,Python,Python 2.7,我正在使用从YAML对象获得的Python(2.7)上的嵌套字典,我有几个问题一直试图通过阅读得到答案,但没有成功。我对Python有些陌生 最简单的函数之一是读取整个字典并输出其中存在的所有键的列表。我在开始时使用下划线,因为这个函数后来会被类中的其他人使用 类Myclass(对象): @静力学方法 定义获取密钥列表(d,密钥列表): 对于键,d.iteritems()中的值: keylist.append(键) 如果isinstance(值,dict): Myclass.\u获取密钥\u列表

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

最简单的函数之一是读取整个字典并输出其中存在的所有键的列表。我在开始时使用下划线,因为这个函数后来会被类中的其他人使用

类Myclass(对象):
@静力学方法
定义获取密钥列表(d,密钥列表):
对于键,d.iteritems()中的值:
keylist.append(键)
如果isinstance(值,dict):
Myclass.\u获取密钥\u列表(d.get(key),keylist)
返回列表(设置(键列表))
def diff(自身,dict2):
keylist=[]
all_keys 1=self.\u get_key_list(self.d,keylist)
all_keys2=self._get_KEYST_列表(dict2,KEYSTLIST)
... # 更多代码
问题1:这样做正确吗?出于这个原因,我不确定使用静态方法是否是一种好的做法。由于
self.\u get\u key\u list(d,keylist)
是递归的,因此我不希望在递归调用函数后将“self”作为第一个参数,这是常规实例方法的情况

我有一大堆我正在使用的静态方法,但是我已经在很多地方读过了,当我经常使用这些方法时,它们可能不是很好的实践。我还认为我可以让它们成为模块函数,但我希望它们与类绑定


问题2:如何在递归函数中初始化空列表并更新它,而不是将参数
keylist
传递给
self.\u get\u key\u list(d,keylist)
?在内部初始化它会每次都将其重置为[]。

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

要初始化一个参数,我们通常在参数列表中为其指定一个默认值,但如果它需要是一个可变对象(如本例中的空列表),则需要将其默认为None,并在函数中初始化它,以便在下一次调用中不会重用list引用:

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

我将把
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
如果调用者确实需要列表,而不是iterable,那么让调用者将集合转换为列表

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

如果您担心效率(例如,从dict获取大量重复键),可以返回到将单个集合/列表作为显式参数贯穿调用,但不要将其设置为可选参数;只需要初始调用方提供要更新的集合/列表。要强调第二个参数将发生变异,只需在函数返回时返回
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

keylist
的默认值设为一个列表,使得
keylist
在所有初始调用中都是相同的列表。否,只有当
keylist
未作为
\u get\u key\u list
@blhsing的第二个参数提供时,才会使用默认值如果您甚至不使用对象本身,
self
的目的是什么?这让我有点困惑。@blhsing一旦你在默认值中添加了一些东西,它就会留在那里;没有显式参数的每次调用都不会得到一个新的空列表。@chepner,这正是OP想要的。只有在递归过程中,我们才希望将更新的
keylist
传递到下一个级别的
\u get\u key\u list
。谢谢,我肯定会直接使用集合。因此,即使它是一个“私有”方法,仅由该类中的其他实例方法使用,在该类之外编写它似乎可以吗?稍后我将把这个类导入到另一个文件中。如果这个函数对这个类没有什么特别独特的地方,就把它变成一个函数。至少,引用函数比引用方法更容易。