For loop returns None 进行一些迭代

For loop returns None for some iterations

我有一个嵌套的字典,想遍历它并附加到过滤器(我将发送给 BE 的 JSON)。看起来它循环的次数超过了应有的次数,这就是为什么有 None 值的原因。只有当我将函数分成两个更小的函数时才会发生这种情况。你能帮我理解为什么会这样吗?

变量

${filters_to_add}=    {1: {"sf":'Previous Status', "AND":"", "operatorId": 'in the selection list'},  2: {"sf":'Job Requisition', "AND":"", "operatorId": 'not in the selection list'},
...    3: {"sf":'Job Profile', "AND":"", "operatorId": 'in the selection list', "targetInstances": 'Marketing'},
...    4: {"sf":'Stage', "AND":"", "operatorId": 'not in the selection list', "targetInstances": 'Offer'},
...    5: {"sf":'Candidate', "AND":"", "operatorId": 'is not empty'}, 'Primary Work Location':{"AND":"", "operatorId": 'is empty'},
...    6: {"sf":'Candidate', "AND":"", "operatorId": 'is empty'}} 

正确运行的代码

def _prepare_filters_json(self, pipeline: str, filters_to_add: dict):
        source_fields = self.ssi_get_filter_source_fields(pipeline).json_path("$.data")
        filters = self._get_filters(pipeline)
        for key, value in filters_to_add.items():
            for field_to_add in value.keys():
                new_filter = {"type": 'CONDITION', "id": 'any_id', "field": {}, "operatorId": 'null'}
                if "AND" in value.keys():
                    for source_field in source_fields:
                        if source_field["descriptor"] == value[field_to_add]:
                            new_filter["field"] = source_field
                            new_filter["operatorId"] = value["operatorId"]
                            if "dataType" in value[field_to_add] and source_field["returnType"] == value["dataType"]:
                                new_filter[value["targetType"]] = value["targetValue"]
                            if "targetInstances" in value.keys():
                                new_filter = self._set_filter_comp_oper_value(pipeline, new_filter, source_field["id"],value)
                            if "useValueFromAnotherField" in value.keys():
                                new_filter = self._set_filter_value_from_another_field(pipeline, new_filter,source_field["id"], value)
                            filters["children"].append(dict(new_filter))
        return self._prepare_json(pipelineId=pipeline, filter=filters)

并且returns正确输出

{'configurationId': '634d8914d6f4010030bb489b5ed10000',
 'filter': {'children': [{'field': {'descriptor': 'Previous Status',
                                    'id': '228cf38209cb10000fd3509c5c9200a3',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'in the selection list',
                          'type': 'CONDITION'},
                         {'field': {'descriptor': 'Job Requisition',
                                    'id': '7b9a3101caaf1000039078f00c56001e',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'not in the selection list',
                          'type': 'CONDITION'},
                         {'field': {'descriptor': 'Job Profile',
                                    'id': '7b9a3101caaf100006c9a6dea9d6006f',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'in the selection list',
                          'targetInstances': [{'descriptor': 'Marketing',
                                               'id': 'd3bfb62d3bd344c8abf95b8be88d6137'}],
                          'type': 'CONDITION'},
                         {'field': {'descriptor': 'Stage',
                                    'id': 'b6777bdbab7d100022197ed8e03a00b3',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'not in the selection list',
                          'targetInstances': [{'descriptor': 'Offer',
                                               'id': '868a8156682541f2aadc2fe90268b75f'}],
                          'type': 'CONDITION'},
                         {'field': {'descriptor': 'Candidate',
                                    'id': 'b6777bdbab7d1000220b76fcba7000b1',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'is not empty',
                          'type': 'CONDITION'},
                         {'field': {'descriptor': 'Candidate',
                                    'id': 'b6777bdbab7d1000220b76fcba7000b1',
                                    'returnType': 'Single instance'},
                          'id': 'any_id',
                          'operatorId': 'is empty',
                          'type': 'CONDITION'}],
            'groupCondition': 'AND',
            'id': 'deb03c24-d520-4a60-86ce-2cca38bea3b2',
            'type': 'GROUP'},
 'pipelineId': 'hiring',
 'version': 1}

returnsNone

的代码
 def _prepare_filters_json(self, pipeline: str, filters_to_add: dict):
        source_fields = self.ssi_get_filter_source_fields(pipeline).json_path("$.data")
        filters = self._get_filters(pipeline)
        for key, value in filters_to_add.items():
            for field_to_add in value.keys():
                new_filter = {"type": 'CONDITION', "id": 'any_id', "field": {}, "operatorId": 'null'}
                if "AND" in value.keys():
                    new_filter = self._set_filter(pipeline, source_fields, new_filter, field_to_add, value)
                    filters["children"].append(dict(new_filter))
        return self._prepare_json(pipelineId=pipeline, filter=filters)

 def _set_filter(self, pipeline, source_fields, new_filter, field_to_add, value):
        for source_field in source_fields:
            if source_field["descriptor"] == value[field_to_add]:
                new_filter["field"] = source_field
                new_filter["operatorId"] = value["operatorId"]
                if "dataType" in value[field_to_add] and source_field["returnType"] == value["dataType"]:
                    new_filter[value["targetType"]] = value["targetValue"]
                if "targetInstances" in value.keys():
                    new_filter = self._set_filter_comp_oper_value(pipeline, new_filter, source_field["id"], value)
                if "useValueFromAnotherField" in value.keys():
                    new_filter = self._set_filter_value_from_another_field(pipeline, new_filter, source_field["id"],value)
                return new_filter

输出错误

{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': '228cf38209cb10000fd3509c5c9200a3', 'descriptor': 'Previous Status', 'returnType': 'Single instance'}, 'operatorId': 'in the selection list'}
None
None
{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': '7b9a3101caaf1000039078f00c56001e', 'descriptor': 'Job Requisition', 'returnType': 'Single instance'}, 'operatorId': 'not in the selection list'}
None
None
{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': '7b9a3101caaf100006c9a6dea9d6006f', 'descriptor': 'Job Profile', 'returnType': 'Single instance'}, 'operatorId': 'in the selection list', 'targetInstances': [{'id': 'd3bfb62d3bd344c8abf95b8be88d6137', 'descriptor': 'Marketing'}]}
None
None
None
{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': 'b6777bdbab7d100022197ed8e03a00b3', 'descriptor': 'Stage', 'returnType': 'Single instance'}, 'operatorId': 'not in the selection list', 'targetInstances': [{'id': '868a8156682541f2aadc2fe90268b75f', 'descriptor': 'Offer'}]}
None
None
None
{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': 'b6777bdbab7d1000220b76fcba7000b1', 'descriptor': 'Candidate', 'returnType': 'Single instance'}, 'operatorId': 'is not empty'}
None
None
None
None
{'type': 'CONDITION', 'id': 'any_id', 'field': {'id': 'b6777bdbab7d1000220b76fcba7000b1', 'descriptor': 'Candidate', 'returnType': 'Single instance'}, 'operatorId': 'is empty'}
None
None

一个简单的错误示例:

def f(ls):
    lx = []
    for x in ls:
        print(f"Element: {x}")
        lx.append(x)
        return lx
    print("Leaving function with `None` value.")

def g(ls):
    lx = []
    for x in ls:
        print(f"Element: {x}")
        lx.append(x)
    return lx

使用 REPL,如果我们:

>>> print("Result = {}".format(f([1,2,3])))
Element: 1
Result = [1]
>>> print("Result = {}".format(g([1,2,3])))
Element: 1
Element: 2
Element: 3
Result = [1, 2, 3]
>>> print("Result = {}".format(f([])))
Leaving function with `None` value
Result = None
>>> print("Result = {}".format(g([])))
Result = []

您在 _set_filter() 函数中所做的是 returning 早...但您也只是 returning 一个值,如果它在 for 循环。如果您传递一个空列表,则根本不会 return 编辑任何内容,因为 None 是默认的 return 值。

请注意,当您将 if 嵌套在 for 中时,如果您传递给 if return 的每个条件都是一个 False 值,则if 中的任何 return 语句永远不会被命中——这是另一种让你的函数结束的方法 returning a None.

具体来说,您的函数:

def _set_filter(self, pipeline, source_fields, new_filter, field_to_add, value):
    for source_field in source_fields:
        if source_field["descriptor"] == value[field_to_add]:
            ... a bunch of things
            return new_filter  # will return if inside this `if` conditional
        # will move on to the next item in the iteration if the `if` conditional was false.
    # Will return `None` if every element in `source_fields` failed to get inside the `if` conditional (all evaluated to `False`)
    #   or if `source_fields` was an empty list.

Dicts 附录

您可以用来简化逻辑的一个技巧是对字典使用 get() 方法。

dx = {"a": 1, "b": 2}  # A dictionary
print(dx.get("a"))  # Prints '1'
print(dx.get("c"))  # Prints 'None'
print(dx.get("c", 0)  # Prints '0'

与其使用内置索引,这要求您在检索值或冒抛出异常的风险之前进行检查,不如使用它来分配合理的结果。

此外,您不需要使用 keys() 函数来测试是否存在:

>>> dx = {"a": 1, "b": 2}
>>> "a" in dx
True
>>> "a" in dx.keys()
True