在Python中验证一长串条件的优雅方式

6 投票
7 回答
5600 浏览
提问于 2025-04-16 14:24

我有一长串条件需要验证是否为真。为了避免写一大堆的if条件,我想尝试一种“创新”的方式,这样我觉得更容易读懂。但是我想问,这样做是否是最优的方式?

或者有没有更符合Python风格的做法?顺便说一下,请给我一个替代方案,而不是直接回答“不是”,谢谢!

以下是代码片段:

def site_exists(site):
    """
    returns the sitebean if it exists,
    else returns false
    """
    vpadmin_service = _get_vpadmin_service(site)
    all_sites = VpAdminServiceUtil.getSites(vpadmin_service)
    for site_listing in all_sites:
        if site.getId():
            #condition check
            try:
                assert site.getId() == site_listing.getId()
                assert site.getName() == site_listing.getName()
                assert site.getCustomer().getId() == site_listing.getCustomer().getId()
            except AssertionError:
                continue
            #pass conditions
            return site_listing
        #no id, so just check for name and customer
        else:
            #condition check
            try:
                assert site.getName() == site_listing.getName()
                assert site.getCustomer().getId() == site_listing.getCustomer().getId()
            except AssertionError:
                continue
            #pass conditions
            site.setId(site_listing.getId())
            return site_listing
    return False

7 个回答

3

我会在 site 上实现一个 is_same 方法,然后在 for 循环中调用它。

all_sites = VpAdminServiceUtil.getSites(vpadmin_service)
for site_listing in all_sites:
    if site_listing.is_same(site, set_id=True):
        return site_listing

至于如何实现这个方法(这才是你真正想问的问题),我建议可以这样做:

...
if self.getName()     != site.getName():     return False
if self.getCustomer() != site.getCustomer(): return False
...
return True
10

一种更简单的方法是把条件放在一个元组里,然后比较这些元组:

def site_info(s):
    return s.getId(), s.getName(), s.getCustomer().getId()

if site_info(site) == site_info(site_listing):
    return site_listing
else:
    continue

如果你有很多条件,或者这些条件比较复杂,另一种方法是创建一个生成器来处理这些条件,然后用 anyall 来比较:

import itertools
def iter_site_info(s):
    yield s.getId()
    yield s.getName()
    yield s.getCustomer().getId()

if all(x==y for (x, y) in itertools.izip(iter_site_info(site), iter_site_info(site_listing)):
    return site_listing
else:
    continue

我不确定 Jython 是否有 anyall 这两个功能,但其实写这两个功能很简单。

补充 - anyall 是在 Python 2.5 版本中出现的,所以 Jython 应该也有这两个功能。

6

用异常来控制程序的流程是不好的!而且这样会严重影响你的性能。假设某个条件在10次中只有1次会成立?那么在最糟糕的情况下,你就得处理9个异常,这样会带来很大的性能损失。

如果你想让代码更容易读懂,可以试试:

        if (
            condition1 and \
            condition2 and \
            condition3
            ):
            # do something

对于修改后的版本,这应该是等价的:

for site_listing in all_sites:
    if site.getName() == site_listing.getName() and site.getCustomer().getId() == site_listing.getCustomer().getId():
        if not site.getId():
            site.setId(site_listing.getId())
        if site.getId() == site_listing.getId():
            return site_listing

撰写回答