简体   繁体   English

如何使用字典来实现“switch/case”,其中评估值可能会失败?

[英]How can I use a dictionary to implement "switch/case", where evaluating the values could fail?

I am working on the following problem: https://www.codewars.com/kata/5266876b8f4bf2da9b000362/train/python我正在解决以下问题: https://www.codewars.com/kata/5266876b8f4bf2da9b000362/train/python

Implement a function likes:: [String] -> String, which must take in input array, containing the names of people who like an item.实现一个 function likes:: [String] -> String,它必须接受输入数组,包含喜欢某个项目的人的姓名。 It must return the display text as shown in the examples:它必须返回示例中所示的显示文本:

 likes([]) # must be "no one likes this" likes(["Peter"]) # must be "Peter likes this" likes(["Jacob", "Alex"]) # must be "Jacob and Alex like this" likes(["Max", "John", "Mark"]) # must be "Max, John and Mark like this" likes(["Alex", "Jacob", "Mark", "Max"]) # must be "Alex, Jacob and 2 others like this"

Here is my solution:这是我的解决方案:

def likes(names):
    length = len(names)
    switcher = {
        0: "no one likes this",
        1: f"{names} likes this", 
        2: f'{names[0]} and {names[1]} like this', 
        3: f'{names[0]}, {names[1]} and {names[2]} like this', 
        4: f'{names[0]}, {names[1]} and ({length} - 2) others like this'
    }
    return switcher.get(length)

But if I call it with a list containing fewer than 2 names, I get the IndexError:但是,如果我使用包含少于 2 个名称的列表来调用它,我会得到 IndexError:

2: f'{names[0]} and {names[1]} like this',
IndexError: list index out of range

Why can't I do it this way or if I can how do I get around this?为什么我不能这样做,或者如果我可以,我该如何解决?

 length = len(names) switcher = { 0: "no one likes this", 1: f"{names} likes this", 2: f'{names[0]} and {names[1]} like this', 3: f'{names[0]}, {names[1]} and {names[2]} like this', 4: f'{names[0]}, {names[1]} and ({length} - 2) others like this' } return switcher.get(length)

Here, presumably you were expecting that this behaves like a chained if / elif statement like this:在这里,大概您期望它的行为类似于这样的链式if / elif语句:

if length == 0:
    return "no one likes this"
elif length == 1:
    return f"{names} likes this"
elif length == 2:
    return f'{names[0]} and {names[1]} like this'

and so on, where each return expression is only evaluated if the corresponding condition is true.依此类推,其中每个返回表达式仅在相应条件为真时才被评估。

But that is not the case.但事实并非如此。 The dictionary switcher is built completely before the length comes into play.字典switcher是在length起作用之前完全构建的。 So when passing a list names with less than 2 elements, the values for 2, 3, and 4 elements are still evaluated, which raises an IndexError , since names[1] , or even names[0] do not exist.因此,当传递少于 2 个元素的列表names时,仍会评估 2、3 和 4 个元素的值,这会引发IndexError ,因为names[1]甚至names[0]都不存在。

The clearest way around this is just using if / elif / else .解决这个问题最清晰的方法就是使用if / elif / else


You could create a dictionary containing functions which in turn return the formatted strings.可以创建一个包含函数的字典,这些函数又返回格式化的字符串。

The "else" case should not be in the 4 key, but corresponds to the default value returned by .get() : “else”的情况不应该在4键中,而是对应于.get()返回的默认值:

def likes(names):
    length = len(names)
    switcher = {
        0: lambda _: "no one likes this",
        1: lambda n: f"{n[0]} likes this", 
        2: lambda n: f'{n[0]} and {n[1]} like this', 
        3: lambda n: f'{n[0]}, {n[1]} and {n[2]} like this'
    }
    formatter = switcher.get(
        length,
        lambda n: f'{n[0]}, {n[1]} and ({length} - 2) others like this'
    )
    return formatter(names)

Note that in the 1 case you should use names[0] , not names .请注意,在1一种情况下,您应该使用names[0] ,而不是names

The problem here is that the dictionary tries to create all its elements when you define switcher , and fails when lenght <= 2 since the third element ( names[2] ) does not exist and thus, it raises an error这里的问题是字典在定义switcher时尝试创建其所有元素,并且在lenght <= 2时失败,因为第三个元素( names[2] )不存在,因此会引发错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM