如何遍历函数参数?
How can I loop through function arguments?
def grade(*score):
for i in range(0, score):
if score >= 90:
return "A"
elif score >=80:
return "B"
elif score >=70:
return "C"
elif score >=60:
return "D"
else:
return "F"
print(grade(87, 92, 100, 54, 72, 84, 81, 74))
我希望能够遍历参数并return每次循环都得到正确的成绩。
for student in grade_tuple:
print(grade(student))
- 假设你重写 grade() 只期望一个分数...
您可以使用 for 循环,将每个成绩附加到列表中,然后 return 列表。
def grade(*score):
grades = []
for i in score:
if i >= 90:
grades.append("A")
elif i >=80:
grades.append("B")
elif i >=70:
grades.append("C")
elif i >=60:
grades.append("D")
else:
grades.append("F")
return grades
print(grade(87, 92, 100, 54, 72, 84, 81, 74))
您可以尝试这种有趣的紧凑方式(我不确定您是否弄错了,但是是的,这适用于元组):
def grade(score):
scores = {range(90,101):"a", range(80,90):"b", range(70,80):"c", range(60,70):"d", range(1,60):"f"}
return tuple([scores[gradeRange] for i in score for gradeRange in scores.keys() if i in gradeRange])
print(grade((100,30,70)))
("a","f","c")
如评论中所述,这里有比循环 args 更好的设计。将函数应用于单个元素,这是评估等级所需的最小粒度单位。将循环放入您可能想应用于多个元素的每个函数中充其量是浪费打字,最坏的情况下确实会对调用者造成可读性和维护伤害。
根据经验,当一个函数在一个单元上运行时,将循环移动到调用者(例如int
)。仅当需要对可迭代对象进行操作时才在函数内部循环(例如 sort
、min
、sum
)。
此外,避免使用长 if
-else
链。如果你有 30 个桶而不是 5 个怎么办?编写 30 if
-else
语句不可扩展。称之为过早,但当我的 if
-else
链长超过 3 左右时,我往往会感到不安。
这是我的建议,它利用了大多数桶都可以被 10 整除的事实,我们只需要处理 <60 是一个巨大的桶而 100 需要一个额外的桶这一事实。现在我们完全消除分支。
>>> def grade(x): return "FFFFFFDCBAA"[x//10]
...
>>> grade(99)
'A'
>>> grade(100)
'A'
>>> grade(80)
'B'
>>> grade(89)
'B'
>>> grade(60)
'D'
>>> grade(59)
'F'
如果你想变得健壮,在另一行中折腾并检查边界,如果参数超出范围则引发 IndexError
如果参数不正确则可能引发 ValueError
类型。
有了我们新的 grade
函数,我们可以根据调用者的选择将其应用于单个成绩或可迭代的成绩:
>>> grades = [87, 92, 100, 54, 72, 84, 81, 74]
>>> [grade(x) for x in grades]
['B', 'A', 'A', 'F', 'C', 'B', 'B', 'C']
>>> list(map(grade, grades)) # alternately
['B', 'A', 'A', 'F', 'C', 'B', 'B', 'C']
在实际的应用程序中,grades
列表并不是凭空出现的一堆文字或变量——它必须处于某种数据结构的状态。如果你坚持你的函数设计as-is,你要么有一个额外的循环,要么你被困在打包和解包数据结构中,或者两者兼而有之。
还有一个 semantic/readability 问题:grade(100, 20, 64)
不清楚应该进行什么操作。 grade
是要 return 所有分数的平均值并得出最终成绩吗?缩减是像这样的可变参数函数的典型模式(例如 sum
、min
等)。当调用者使用 [grade(x) for x in grades]
时,更清楚的是我们正在使用映射操作,将函数 grade
单独应用于每个元素而不是作为一个单元的集合。按照这个逻辑,更好的函数名称可能是 score_to_letter_grade
或类似的名称,它清楚地描述了正在执行的 1:1 操作。
此外,如果您只想对一件事进行评分,那么无论什么内容,您都必须使用列表作为输出,这几乎是瞬间 deal-breaker 以保持调用者的清洁。如果内置 int
像这样工作,那在后面会是一个非常大的痛苦:x = int(x)[0]
只是将 x
从整数解析为字符串。
这里的情况并没有那么可怕,因为代码量如此之小,但是大的设计问题可以像这样在微观尺度上进行解释,当应用于更大的代码库时,这种责任的错误分配会产生设计债务。
def grade(*score):
for i in range(0, score):
if score >= 90:
return "A"
elif score >=80:
return "B"
elif score >=70:
return "C"
elif score >=60:
return "D"
else:
return "F"
print(grade(87, 92, 100, 54, 72, 84, 81, 74))
我希望能够遍历参数并return每次循环都得到正确的成绩。
for student in grade_tuple:
print(grade(student))
- 假设你重写 grade() 只期望一个分数...
您可以使用 for 循环,将每个成绩附加到列表中,然后 return 列表。
def grade(*score):
grades = []
for i in score:
if i >= 90:
grades.append("A")
elif i >=80:
grades.append("B")
elif i >=70:
grades.append("C")
elif i >=60:
grades.append("D")
else:
grades.append("F")
return grades
print(grade(87, 92, 100, 54, 72, 84, 81, 74))
您可以尝试这种有趣的紧凑方式(我不确定您是否弄错了,但是是的,这适用于元组):
def grade(score):
scores = {range(90,101):"a", range(80,90):"b", range(70,80):"c", range(60,70):"d", range(1,60):"f"}
return tuple([scores[gradeRange] for i in score for gradeRange in scores.keys() if i in gradeRange])
print(grade((100,30,70)))
("a","f","c")
如评论中所述,这里有比循环 args 更好的设计。将函数应用于单个元素,这是评估等级所需的最小粒度单位。将循环放入您可能想应用于多个元素的每个函数中充其量是浪费打字,最坏的情况下确实会对调用者造成可读性和维护伤害。
根据经验,当一个函数在一个单元上运行时,将循环移动到调用者(例如int
)。仅当需要对可迭代对象进行操作时才在函数内部循环(例如 sort
、min
、sum
)。
此外,避免使用长 if
-else
链。如果你有 30 个桶而不是 5 个怎么办?编写 30 if
-else
语句不可扩展。称之为过早,但当我的 if
-else
链长超过 3 左右时,我往往会感到不安。
这是我的建议,它利用了大多数桶都可以被 10 整除的事实,我们只需要处理 <60 是一个巨大的桶而 100 需要一个额外的桶这一事实。现在我们完全消除分支。
>>> def grade(x): return "FFFFFFDCBAA"[x//10]
...
>>> grade(99)
'A'
>>> grade(100)
'A'
>>> grade(80)
'B'
>>> grade(89)
'B'
>>> grade(60)
'D'
>>> grade(59)
'F'
如果你想变得健壮,在另一行中折腾并检查边界,如果参数超出范围则引发 IndexError
如果参数不正确则可能引发 ValueError
类型。
有了我们新的 grade
函数,我们可以根据调用者的选择将其应用于单个成绩或可迭代的成绩:
>>> grades = [87, 92, 100, 54, 72, 84, 81, 74]
>>> [grade(x) for x in grades]
['B', 'A', 'A', 'F', 'C', 'B', 'B', 'C']
>>> list(map(grade, grades)) # alternately
['B', 'A', 'A', 'F', 'C', 'B', 'B', 'C']
在实际的应用程序中,grades
列表并不是凭空出现的一堆文字或变量——它必须处于某种数据结构的状态。如果你坚持你的函数设计as-is,你要么有一个额外的循环,要么你被困在打包和解包数据结构中,或者两者兼而有之。
还有一个 semantic/readability 问题:grade(100, 20, 64)
不清楚应该进行什么操作。 grade
是要 return 所有分数的平均值并得出最终成绩吗?缩减是像这样的可变参数函数的典型模式(例如 sum
、min
等)。当调用者使用 [grade(x) for x in grades]
时,更清楚的是我们正在使用映射操作,将函数 grade
单独应用于每个元素而不是作为一个单元的集合。按照这个逻辑,更好的函数名称可能是 score_to_letter_grade
或类似的名称,它清楚地描述了正在执行的 1:1 操作。
此外,如果您只想对一件事进行评分,那么无论什么内容,您都必须使用列表作为输出,这几乎是瞬间 deal-breaker 以保持调用者的清洁。如果内置 int
像这样工作,那在后面会是一个非常大的痛苦:x = int(x)[0]
只是将 x
从整数解析为字符串。
这里的情况并没有那么可怕,因为代码量如此之小,但是大的设计问题可以像这样在微观尺度上进行解释,当应用于更大的代码库时,这种责任的错误分配会产生设计债务。