4

内部リスト項目の平均として外部的にそれ自体を表すが、それ以外の場合はリストとして動作するPythonリストが必要です。TypeErrorフロートにキャストできないアイテムが追加された場合は、を上げる必要があります。

私が立ち往生している部分は上げてTypeErrorいます。、、、、スライスによる設定など.append、任意のリストメソッドを介して追加された無効なアイテムに対して発生する必要があります。.extend+=

リストに追加された新しいアイテムをインターセプトして検証する方法はありますか?

でリスト全体を再検証しようとしまし__getattribute__たが、呼び出されたときは古いバージョンのリストにしかアクセスできません。さらに、初期化、のような演算子+=、またはのようなスライスも呼び出されませんmylist[0] = 5

何か案は?

4

6 に答える 6

3

MutableSequenceから継承し、必要なメソッドだけでなく、Sequences だけの範囲外にあるその他のメソッド (ここでの演算子など) を実装します。これにより、イテレータと含む機能を自動的に生成しながら、リストのような機能の演算子操作を変更できます。

ところでスライスをチェックしたい場合はisinstance(key, slice)__getitem__(および/または__setitem__)メソッドで行う必要があります。myList[0] のような単一のインデックスはスライス リクエストではなく、単一のインデックスであり、myList[:0] は実際のスライス リクエストであることに注意してください。

于 2012-08-30T17:04:20.977 に答える
2

array.arrayクラスは次の部分を処理しますfloat

class AverageList(array.array):
    def __new__(cls, *args, **kw):
        return array.array.__new__(cls, 'd')
    def __init__(self, values=()):
        self.extend(values)
    def __repr__(self):
        if not len(self): return 'Empty'
        return repr(math.fsum(self)/len(self))

そしていくつかのテスト:

>>> s = AverageList([1,2])
>>> s
1.5
>>> s.append(9)
>>> s
4.0
>>> s.extend('lol')
Traceback (most recent call last):
  File "<pyshell#117>", line 1, in <module>
    s.extend('lol')
TypeError: a float is required
于 2012-08-30T16:57:05.030 に答える
1

listリストに要素を追加するクラスには 7 つのメソッドがあり、チェックする必要があります。コンパクトな実装の 1 つを次に示します。

def check_float(x):
    try:
        f = float(x)
    except:
        raise TypeError("Cannot add %s to AverageList" % str(x))

def modify_method(f, which_arg=0, takes_list=False):
    def new_f(*args):
        if takes_list:
            map(check_float, args[which_arg + 1])
        else:
            check_float(args[which_arg + 1])
        return f(*args)
    return new_f

class AverageList(list):
    def __check_float(self, x):
        try:
            f = float(x)
        except:
            raise TypeError("Cannot add %s to AverageList" % str(x))

    append = modify_method(list.append)
    extend = modify_method(list.extend, takes_list=True)
    insert = modify_method(list.insert, 1)
    __add__ = modify_method(list.__add__, takes_list=True)
    __iadd__ = modify_method(list.__iadd__, takes_list=True)
    __setitem__ = modify_method(list.__setitem__, 1)
    __setslice__ = modify_method(list.__setslice__, 2, takes_list=True)
于 2012-08-30T17:10:42.017 に答える
1

実際、最良の答えは、「しない」かもしれません。

リストに追加されたすべてのオブジェクトをチェックすると、計算コストが高くなります。これらのチェックを行うことで何を得ることができますか? あなたが得るものはほとんどないように私には思えます。私はそれを実装しないことをお勧めします。

Python は型をチェックしません。そのため、1 つのオブジェクトの型を少しだけチェックしようとしても、あまり意味がありません。

于 2012-08-30T17:16:57.370 に答える
0

MutableSequenceモジュール内の抽象基本クラスを基本クラスとして使用してサブクラスを作成する方法を次に示しますcollections(完全にはテストされていません -- 読者の演習です ;-):

import collections

class AveragedSequence(collections.MutableSequence):
    def _validate(self, x):
        try: return float(x)
        except: raise TypeError("Can't add {} to AveragedSequence".format(x))
    def average(self):  return sum(self._list) / len(self._list)
    def __init__(self, arg):  self._list = [self._validate(v) for v in arg]
    def __repr__(self):  return 'AveragedSequence({!r})'.format(self._list)
    def __setitem__(self, i, value):  self._list[i] = self._validate(value)
    def __delitem__(self, i):  del self._list[i]
    def insert(i, value):  return self._list.insert(i, self._validate(value))
    def __getitem__(self, i):  return self._list[i]
    def __len__(self):  return len(self._list)
    def __iter__(self):  return iter(self._list)
    def __contains__(self, item):  return item in self._list

if __name__ == '__main__':
    avgseq = AveragedSequence(range(10))
    print avgseq
    print avgseq.average()
    avgseq[2] = 3
    print avgseq
    print avgseq.average()
    # ..etc
于 2012-08-30T19:10:35.837 に答える
0

一般的なアプローチは、vom リストを継承し、append、extend などの特定のメソッドを上書きする独自のクラスを作成することです。これには、おそらく Python リストの魔法のメソッドも含まれます (詳細については、この記事を参照してください: http://www.rafekettler. com/magicmethods.html#sequence )。

検証のために、__setitem__(self, key, value) を上書きする必要があります

于 2012-08-30T17:00:03.003 に答える