1

リストをフィルタリングするリスト内包表記があります:

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

この投稿 (リストを複製せずにリスト自体を循環させながらリスト要素を削除する方法) で、リストの重複を避けて循環させるためのより良い方法があるかどうかを尋ねます。

コミュニティは、リストの変更を適切に回避し、例外の問題を無視した場合に適用可能なリスト内包表記を使用するように私に答えました。

あなたの観点で代替ソリューションはありますか?リスト内包表記を使用して、そのように例外を管理できますか? この種の状況で大きなリストを使用している場合 (何が大きいと考えなければなりませんか?)、別の代替手段を見つける必要がありますか?

4

4 に答える 4

9

少し補助機能を使用します。

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、コード全体の構造は非常に単純です。

于 2010-02-10T04:08:08.357 に答える
1

いくつかのコメント:

まず第一に、リスト内包[expression for var in iterable]表記はコピーを作成します。リストのコピーを作成したくない場合は、ジェネレータ式を使用します(expression 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()
于 2010-02-10T02:29:25.557 に答える
0

obj.mycond() を呼び出す obj のメソッドを定義できますが、例外もキャッチします

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
于 2010-02-10T02:29:17.993 に答える
0

リストをコピーして要素を削除する代わりに、空のリストから始めて、必要に応じてメンバーを追加します。このようなもの:

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

構文はそれほどきれいではありませんが、不必要な削除を行わなくても、リスト内包表記とほぼ同じことを行うことができます。

リストの最後以外の場所に要素を追加または削除すると、何かを削除するときに、その後にあるすべてのアイテムを調べてインデックスから1を引く必要があるため、遅くなります。それ以外のものを追加する場合も同じです。をインデックスに追加する必要があります。その後のすべての要素の位置を更新します。

于 2010-02-10T02:22:50.187 に答える