以优雅的方式编写业务规则,链接可能不存在的属性

发布于 2024-12-20 16:40:39 字数 800 浏览 2 评论 0原文

看一下这段代码:

>>> class c(object):
...    pass
... 
>>> a=c()
>>> if a.b.c:
...    print 'hello'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'c' object has no attribute 'b'

安静!这不是问题。请继续阅读:

当有人开发企业软件(例如使用 django)时必须编写业务规则。 该规则看起来像

if invoice.customer.adress.country in ...:
    invoice.makeSomeSpecialOffer()

但有时,表达式涉及的对象之一不存在。然后,为了避免错误,我应该将句子重写为:

if invoice.customer and
   invoice.customer.adress and
   invoice.customer.adress.country and
   invoice.customer.adress.country in ...

这可读性较差! (您也可以尝试使用 hasattr,但可读性也较差)。

我的工作是将 if 语句包含在 try 中,但是有一种更优雅或更简洁的方法来避免这种错误吗?您最喜欢哪种技术?

Take a look to this code:

>>> class c(object):
...    pass
... 
>>> a=c()
>>> if a.b.c:
...    print 'hello'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'c' object has no attribute 'b'

Quiet! this is not the question. Please, continue reading:

When someone develops enterprise software (with django for example) must write business rules.
This rules looks like

if invoice.customer.adress.country in ...:
    invoice.makeSomeSpecialOffer()

But some times, one of the objects involveds on expression don't exists. Then, to avoid errors I sould rewrite sentence as:

if invoice.customer and
   invoice.customer.adress and
   invoice.customer.adress.country and
   invoice.customer.adress.country in ...

This is less readable! (also you can try with hasattr but is alse less readable).

My work arround is enclose if statement into a try, but there is a more elegant or pythatonic way to avoid this kind of errors? Which is your favorite technique?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慵挽 2024-12-27 16:40:39

要检查链接属性,以下函数可能会有所帮助:

def get_chainedattr(parobj, *args):
    try:        
        ret = parobj
        for arg in args:
            ret = getattr(ret, arg)   
        return ret
    except AttributeError:
        return None

我不确定它是否更具可读性,但通过使用此函数,您的示例可以编写为:

if get_chainedattr(invoice, "customer", "adress", "country") in ...:
   invoice.makeSomeSpecialOffer()

To check chained attributes the following function might help:

def get_chainedattr(parobj, *args):
    try:        
        ret = parobj
        for arg in args:
            ret = getattr(ret, arg)   
        return ret
    except AttributeError:
        return None

I am not sure if it is more readable but by using this function your example can be written as:

if get_chainedattr(invoice, "customer", "adress", "country") in ...:
   invoice.makeSomeSpecialOffer()
败给现实 2024-12-27 16:40:39

这不太可读! (你也可以尝试使用 hasattr 但也更少
可读)。

另一种选择是包含在 try 'except 块中。

try:
    if invoice.customer.adress.country in ...:
        invoice.makeSomeSpecialOffer()
except AttributeError:
    None

您可以进行主动检查(例如 hasattr),也可以进行被动检查(例如 try- except)。可读性是一种感知,这两种方法都是例外的。

This is less readable! (also you can try with hasattr but is alse less
readable).

Another option would be to enclose in a try 'except block.

try:
    if invoice.customer.adress.country in ...:
        invoice.makeSomeSpecialOffer()
except AttributeError:
    None

Either you can make a proactive check like hasattr or a reactive like try-except. Readability is a perception and both the approach is except-able.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文