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
我有一个嵌套的字典,想遍历它并附加到过滤器(我将发送给 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