更为Pythonic的条件变量赋值方式

4
这是我想要做的事情:
  1. 获取几个参数
  2. 根据这些参数组成一个字符串
  3. 返回该字符串
然而,对于这个问题,我看到有3种可能的方法:
def form_statement(subject, verb, object):
    greetings = ""
    if subject in ("Paul", "Raj"):
        greetings = "mister"
    return "%s %s %s %s" % (subject, verb, object, greetings)

这个的第二种方法是:
def form_statement(subject, verb, object):
    if subject in ("Paul", "Raj"):
        greetings = "mister"
    else:
        greetings = ""
    return "%s %s %s %s" % (subject, verb, object, greetings)

第三种方式是:

def form_statement(subject, verb, object):
    greetings = "mister" if subject in ("Paul", "Raj") else ""
    return "%s %s %s %s" % (subject, verb, object, greetings)

有没有其他更好的方法来做类似这样的事情?目前我选择第一种方式,因为获取问候语字符串的处理本身就是一个函数并且在使用第三种方法时会让行超过80个字符。

编辑:似乎有人困惑我在问哪种方法更好(因为他们认为这是基于意见的)。在这里,我试图找到是否有更好的方法,并且给出了我能想到的东西的例子,以便别人不会把它们作为答案。正如其中一个答案所提到的,我发现在类似情况下使用字典对我更好。


1
所有的解决方案看起来都不错。第一个是“安全”的,因为你总是会得到一些值来赋给 greetings。第二个更易读,但逻辑更复杂,你可能会忘记在最后一个语句中设置 greetings 的值而导致未定义变量错误。我最喜欢的是最后一个,它既安全,又易读,而且很短。 - Jan Vlcinsky
4个回答

1
一种Pythonic的方法是使用字典来保存主题及其相关的问候语,然后使用dict.get()方法。如果字典中缺少键,则该方法还可以接受第二个参数作为返回值。
main_dict = {"Paul":"mister", "Raj": "mister"}

def form_statement(main_dict, subject, verb, object):
    greetings = main_dict.get(subject, '')
    return "{} {} {} {}".format(subject, verb, object, greetings)

当你处理较大的数据集时,这种方法将展现其优势。因为字典使用哈希表,它们的索引顺序为O(1)。并且你可以为每个动词使用不同的结果。


函数的第一个参数有一个错别字,应该是subject而不是subjects。使用字典的好方法。 - thiruvenkadam
另外,我认为应该是 subjects.get(subject, '') - tobias_k
@thiruvenkadam 我以为你正在检查元组中 verb 的成员资格。请检查编辑。 - Mazdak
@tobias_k 是的,已修复。 - Mazdak

1
第一种版本在条件为真时对“greetings”进行了两次赋值。
另外两个版本是等效的。通常应该使用更易读的那个。记住,开发者的时间是宝贵的资源。这就是为什么我会说if-else结构总是适用的,三元条件(A if cond else B)对于一行代码很好。
如果您正在增强现有的代码,请保留其样式。

顺便说一句,使用set可以实现最快速的查找: name in {"Paul", .... }


0
你可以动态地创建一个字典,其中包含所有应该有“先生”称号的姓名和应该有类似头衔的姓名。然后,只需从该字典中获取值,或者在名称不存在的情况下使用默认值""。这样就可以实现字典的创建。
pairings = [(("Paul", "Raj"), "mister"), (("Anna", "Paula"), "madam")]
greetings = {name: title for names, title in pairings for name in names}

def form_statement(subject, verb, object):
    return "%s %s %s %s" % (subject, verb, object, greetings.get(subject, ""))

0
您可以将函数参数视为列表,并使用空格将它们连接起来。由于args是元组形式,因此需要先将其转换为列表。
def form_statement(*args):
    args = list(args)
    if args[0] in ["Paul", "Raj"]:
        args.append("mister")
    return " ".join(args)

这是我的小测试套件(存储在与上面的函数相同的文件中,并通过$ py.test greet.py运行):

def test_paul():
    assert form_statement("Paul", "get", "well") == "Paul get well mister"


def test_raj():
    assert form_statement("Raj", "get", "well") == "Raj get well mister"


def test_else():
    assert form_statement("John", "get", "well") == "John get well"

编辑:添加了更加明确的版本:

正如@thiruvenkadam所指出的那样,原始版本并不是非常明确。这里是函数的一个稍微改进的版本。

def form_statement(subject, verb, object):
    if subject in ["Paul", "Raj"]:
        return " ".join([subject, verb, object, "mister"])
    else:
        return " ".join([subject, verb, object])

以上两种实现的小优点是,它们都没有尾随空格。

1
我对这种方法并不太有信心。“显式优于隐式”。 - thiruvenkadam
@thiruvenkadam 谢谢。你是正确的。(这种反馈是我喜欢在SO答案中看到的)。我添加了一个更明确的版本。 - Jan Vlcinsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接