python 基于实例的类型检查

python instance-based type checking

我有这样的代码:

def transform_incoming_json_item(item, things=[]):
    if isinstance(item, list):
        for thing in item:
            things.append(process_thing(thing))
    elif isinstance(item, dict):
        things.append(process_thing(item))
    return things

是否有更 pythonic 的方式来做到这一点,同时只对 process_thing 进行一次调用(同时保留类型检查和两种情况,循环与不需要循环)?

(注意:"more pythonic" 在编辑中添加以澄清问题。)

如何:对于 dict 情况,将字典转换为包含单个项目(字典对象)的列表:

def transform_incoming_json_item(item, things=[]):
    if isinstance(item, dict):    # <----
        item = [item]             # <----
    if isinstance(item, list):
        things.extend(process_thing(thing) for thing in item)
    return things

注意:参数things在定义时创建(仅一次)。换句话说,当调用函数 transform_incoming_json_item 时,事情并没有被初始化。

如果这不是您想要的,您需要执行以下操作:

def transform_incoming_json_item(item, things=None):
    if things is None:
        things = []
    if isinstance(item, dict):    # <----
        item = [item]             # <----
    if isinstance(item, list):
        things.extend(process_thing(thing) for thing in item)
    return things

利用faltru将dict转成list的思路,可以进一步简化代码为:

def transform_incoming_json_item(item, things=None):
    return ([] if things is None else things +
        [process_thing(thing) for thing in (
         item  if isinstance(item, list) else 
        [item] if isinstance(item, dict) else [])])

如您所见,它相当紧凑。但是,如果列表理解这么长时间让您感到困惑或者不是您的事,那么您显然应该选择其他答案。就个人而言,我发现它们非常适合这种情况,但是 YMMV。