2016-06-09 27 views
3

问题: 我想知道递归地将函数应用于对象中的字符串值而不事先知道它的架构的最pythonic方法吗?最好以足够通用的方式使其成为其他类型操作的可重用组件。递归地将函数应用于字符串值的大多数pythonic方式

上下文: 我处理JSON字符串作为从API请求输入,使用json.loads()加载它,我想之前或之后的任何的去掉所有空白施加验证之前对象中的字符串。我更喜欢这个代码是自适应的,以便模式中的变化不会破坏它。

目前的解决方案:

def strip(obj): 
    return obj.strip() 

def recurse_into(obj, baseaction, basetype=str): 
    if isinstance(obj, basetype): 
     return baseaction(obj) 
    elif isinstance(obj, list): 
     return [recurse_into(o, baseaction, basetype) for o in obj] 
    elif isinstance(obj, tuple): 
     return tuple(recurse_into(o, baseaction, basetype) for o in obj) 
    elif isinstance(obj, dict): 
     return dict((k, recurse_into(v, baseaction, basetype)) 
        for (k, v) in obj.items()) 
    else: 
     return obj 

def generate_recurse(baseaction, basetype=str): 
    def f(obj): 
     return recurse_into(obj, baseaction, basetype) 
    return f 

def recursive_strip_whitespace(obj): 
    clean_whitespace = generate_recurse(strip) 
    return clean_whitespace(obj) 

问题与当前的解决方案: 它看起来非常简洁,这是很难理解正在发生的事情对谁没有写它的人,我真的希望有更可读的方法来做到这一点。或者,这是否真的是最好的?

+0

老实说,这段代码对我来说看起来很干净优雅。如果难以理解,也许更多评论会有所帮助? – recursive

+0

为什么不只是'return recurse_into(obj,strip)',而不是“生成”递归函数,并将其保存到变量中? – bozdoz

+0

为什么不只是使用一个简单的正则表达式? –

回答

0

我的建议是削减一些冗余代码:

def strip(obj): 
    return obj.strip() 

def recurse_into(obj, baseaction, basetype=str): 
    if isinstance(obj, basetype): 
     return baseaction(obj) 
    elif isinstance(obj, list): 
     return [recurse_into(o, baseaction, basetype) for o in obj] 
    elif isinstance(obj, tuple): 
     return tuple(recurse_into(o, baseaction, basetype) for o in obj) 
    elif isinstance(obj, dict): 
     return dict((k, recurse_into(v, baseaction, basetype)) 
        for (k, v) in obj.items()) 
    return obj 

def recursive_strip_whitespace(obj): 
    return recurse_into(obj, strip) 
+0

我也认为'basetype'关键字可能会很笨拙,因为它留下了用'list'作为'basetype'的函数的空间,这意味着它可以检查obj是否是列表的两倍。 – bozdoz

0

同样的方法“反转”将是独立的功能分割的情况,并将它们映射出来。它不那么容易理解,但可能看起来更具可读性。

def strip_obj(obj): 
    return obj.strip() 
def strip_tuple(tuple): 
    return tuple(recurse(obj) for obj in tupl) 
... 
def recurse(root): 
    actions = {basetype: strip_obj, 
       tuple: strip_tuple, 
       ...} 
    return actions[type(root)](root) 

注意,对于iterables你可以“去功能性”与map,但我个人觉得过于密集。同样,您可以通过在actions值中使用lambda来获得meta-juju,但它对于可读性来说也不会太好。

相关问题