我可以捕获列表推导中的错误以确保循环所有列表项吗

发布于 2024-08-21 06:54:07 字数 816 浏览 5 评论 0原文

我有一个过滤列表的列表推导式:

l = [obj for obj in objlist if not obj.mycond()]

但是对象方法 mycond() 可以引发我必须拦截的异常。我需要在循环结束时收集所有错误,以显示哪个对象造成了任何问题,同时我想确保循环所有列表元素。

我的解决方案是:

errors = []
copy = objlist[:]

for obj in copy:
    try:
        if (obj.mycond()):
            # avoiding to touch the list in the loop directly
            objlist.remove(obj) 
    except MyException as err:
        errors = [err]
if (errors):
   #do something

return objlist

在这篇文章中(如何在循环列表本身时删除列表元素而不重复它)我问是否有更好的方法来循环避免列表重复。

社区回答我避免就地列表修改并使用在我忽略异常问题时适用的列表理解。

您认为有替代解决方案吗?我可以使用列表理解以这种方式管理异常吗?在这种情况下并使用大列表(我必须考虑大列表?)我必须找到另一种选择?

I've got a list comprehensions which filter a list:

l = [obj for obj in objlist if not obj.mycond()]

but the object method mycond() can raise an Exception I must intercept. I need to collect all the errors at the end of the loop to show which object has created any problems and at the same time I want to be sure to loop all the list elements.

My solution was:

errors = []
copy = objlist[:]

for obj in copy:
    try:
        if (obj.mycond()):
            # avoiding to touch the list in the loop directly
            objlist.remove(obj) 
    except MyException as err:
        errors = [err]
if (errors):
   #do something

return objlist

In this post (How to delete list elements while cycling the list itself without duplicate it) I ask if there is a better method to cycle avoiding the list duplicate.

The community answer me to avoid in place list modification and use a list comprehensions that is applicable if I ignore the Exception problem.

Is there an alternative solution in your point of view ? Can I manage Exception in that manner using list comprehensions? In this kind of situation and using big lists (what I must consider big ?) I must find another alternative ?

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

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

发布评论

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

评论(4

漆黑的白昼 2024-08-28 06:54:07

我会使用一点辅助功能:

def f(obj, errs):
  try: return not obj.mycond()
  except MyException as err: errs.append((obj, err))

errs = []
l = [obj for obj in objlist if f(obj, errs)]
if errs:
  emiterrorinfo(errs)

请注意,这样您就可以在 errs 中获得所有错误对象与每个对象对应的特定异常,因此诊断可以准确并完成;以及您需要的 l,并且您的 objlist 仍然完好无损,可供进一步使用。不需要列表复制,也不需要对 obj 的类进行任何更改,代码的整体结构非常简单。

I would use a little auxiliary function:

def f(obj, errs):
  try: return not obj.mycond()
  except MyException as err: errs.append((obj, err))

errs = []
l = [obj for obj in objlist if f(obj, errs)]
if errs:
  emiterrorinfo(errs)

Note that this way you have in errs all the errant objects and the specific exception corresponding to each of them, so the diagnosis can be precise and complete; as well as the l you require, and your objlist still intact for possible further use. No list copy was needed, nor any changes to obj's class, and the code's overall structure is very simple.

南巷近海 2024-08-28 06:54:07

一些评论:

首先,列表理解语法 [expression for var in iterable] 确实创建了一个副本。如果您不想创建列表的副本,请使用生成器表达式(express for var in iterable)

发电机如何工作?本质上是通过重复调用对象的 next(obj) 直到引发 GeneratorExit 异常。

根据您的原始代码,您似乎仍然需要过滤列表作为输出。

因此,您可以在性能损失很小的情况下进行模拟:

l = []
for obj in objlist:
   try:
      if not obj.mycond()
         l.append(obj)
   except Exception:
      pass

但是,您可以使用生成器函数重新设计所有内容:

def FilterObj(objlist):
   for obj in objlist:
      try:
         if not obj.mycond()
            yield obj
      except Exception:
         pass

这样,您可以安全地迭代它,而无需同时缓存列表:

for obj in FilterObj(objlist):
   obj.whatever()

A couple of comments:

First of all, the list comprehension syntax [expression for var in iterable] DOES create a copy. If you do not want to create a copy of the list, then use the generator expression (expression for var in iterable).

How do generators work? Essentially by calling next(obj) on the object repeatedly until a GeneratorExit exception is raised.

Based on your original code, it seems that you are still needing the filtered list as output.

So you can emulate that with little performance loss:

l = []
for obj in objlist:
   try:
      if not obj.mycond()
         l.append(obj)
   except Exception:
      pass

However, you could re-engineer that all with a generator function:

def FilterObj(objlist):
   for obj in objlist:
      try:
         if not obj.mycond()
            yield obj
      except Exception:
         pass

In that way, you can safely iterate over it without caching a list in the meantime:

for obj in FilterObj(objlist):
   obj.whatever()
神经暖 2024-08-28 06:54:07

你可以定义一个 obj 的方法来调用 obj.mycond() 但也捕获异常

class obj:

    def __init__(self):
        self.errors = []

    def mycond(self):
        #whatever you have here

    def errorcatcher():
        try:
            return self.mycond()
        except MyException as err:
            self.errors.append(err)
            return False # or true, depending upon what you want

l = [obj for obj in objlist if not obj.errorcatcher()]

errors = [obj.errors for obj in objlist if obj.errors]

if errors:
    #do something

you could define a method of obj that calls obj.mycond() but also catches the exception

class obj:

    def __init__(self):
        self.errors = []

    def mycond(self):
        #whatever you have here

    def errorcatcher():
        try:
            return self.mycond()
        except MyException as err:
            self.errors.append(err)
            return False # or true, depending upon what you want

l = [obj for obj in objlist if not obj.errorcatcher()]

errors = [obj.errors for obj in objlist if obj.errors]

if errors:
    #do something
空名 2024-08-28 06:54:07

不要复制列表并删除元素,而是从空白列表开始并根据需要添加成员。像这样的事情:

errors = []
newlist = []

for obj in objlist:
    try:
        if not obj.mycond():
            newlist.append(obj)
    except MyException as err:
        errors.append(err)
if (errors):
   #do something

return newlist

语法并不那么漂亮,但它会做或多或少与列表理解相同的事情,而无需任何不必要的删除。

在列表末尾以外的任何位置添加或删除元素都会很慢,因为当您删除某些内容时,它需要 遍历它后面的每个项目并从其索引中减去一个,添加也是如此除了需要添加到索引之外的其他内容。 更新其后所有元素的位置。

Instead of copying the list and removing elements, start with a blank list and add members as necessary. Something like this:

errors = []
newlist = []

for obj in objlist:
    try:
        if not obj.mycond():
            newlist.append(obj)
    except MyException as err:
        errors.append(err)
if (errors):
   #do something

return newlist

The syntax isn't as pretty, but it'll do more or less the same thing that the list comprehension does without any unnecessary removals.

Adding or removing elements to or from anywhere other than the end of a list will be slow because when you remove something, it needs to go through every item that comes after it and subtract one from its index, and same thing for adding something except it'll need to add to the index. update the position of all the elements after it.

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