The Pythonic way of validating a long chain of conditions in Python
所以我有一长串的条件应该被证实是真的。我没有把一个很长的
或者有没有一种Python式的方法?附言:请用另一种回答而不是回答"不",谢谢!
这是代码块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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 |
一种更简单的方法是构建条件的元组并比较这些元组:
1 2 3 4 5 6 7 | 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 |
如果您有很多条件,或者条件很昂贵,您可以为这些条件创建一个生成器,并与
1 2 3 4 5 6 7 8 9 10 | 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是否有
edit-
对控制流使用异常是错误的!它也会扼杀你的表演。假设条件在10个案例中的一个是真的?所以在最坏的情况下需要处理9个例外——这会带来巨大的性能成本。
如果需要可读性,请尝试:
1 2 3 4 5 6 | if ( condition1 and \ condition2 and \ condition3 ): # do something |
对于修订版,这应等同于:
1 2 3 4 5 6 | 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 |
我将在
1 2 3 4 | all_sites = VpAdminServiceUtil.getSites(vpadmin_service) for site_listing in all_sites: if site_listing.is_same(site, set_id=True): return site_listing |
关于它的实现(这是您真正的问题),我建议如下:
1 2 3 4 5 | ... if self.getName() != site.getName(): return False if self.getCustomer() != site.getCustomer(): return False ... return True |
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | class WrappedSite(object): def __init__(self, site): self.site = site def __eq__(self, other): if site.getId(): if self.site.getId() != other.site.getId(): return False if self.site.getName() != other.site.getName(): return False if self.site.getCustomer().getId() != other.site.getCustomer().getId(): return False return True |
然后你丑陋的大功能被简化为:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) wsite = WrappedSite(site) for site_listing in all_sites: if wsite == WrappedSite(site_listing): return site_listing return False |
编辑fixed
在控制流中使用异常处理是一种Python式的感觉,"请求宽恕比请求许可更容易"。然而,这并没有延伸到制定规则来打破,只是为了让你可以请求宽恕。
其他人提供了很好的选择。只是想解决原则方面的问题。
使用异常处理程序作为代码目标基本上是一个"goto"。我并不认为它真的有什么问题(尽管古时候围绕着"Goto被认为是有害的"),但是知道它是Goto可能会给你一个不同的视角。
删除一些重复代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def site_exists(site): """ returns the sitebean if it exists, else returns None """ vpadmin_service = _get_vpadmin_service(site) all_sites = VpAdminServiceUtil.getSites(vpadmin_service) for site_listing in all_sites: if (site.getName() == site_listing.getName() and site.getCustomer().getId() == site_listing.getCustomer().getId()): if site.getId(): # if id is set; it should be the same if site.getId() != site_listing.getId(): continue else: # no id; consider it the same site site.setId(site_listing.getId()) #XXX side-effect return site_listing |
注:预计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def same_site(site, other): if site.getId() and site.getId() != other.getId(): # if id is set; it should be the same return False return (site.getName() == other.getName() and site.getCustomer().getId() == other.getCustomer().getId()) def get_site_listing(site): """ returns the sitebean corresponding to `site`, returns None if there is none """ vpadmin_service = _get_vpadmin_service(site) all_sites = VpAdminServiceUtil.getSites(vpadmin_service) return next((s for s in all_sites if same_site(site, s)), None) |
注意:代码不会修改
如果
1 2 3 4 | for site_listing in all_sites: if same_site(site, site_listing): return site_listing return None |
顺便说一句,
1 2 3 4 5 | def same_site(site, other): if site.id and site.id != other.id: # if id is set; it should be the same return False return site.name == other.name and site.customer.id == other.customer.id |
用