1

リストの要素のリストを、属性、タイプ、またはその他の条件で絞り込みたい。

のようなものelements.only_type(Flower).get_nearest_to(player)は、よりもはるかに見栄えがしmin(filter(lambda i: isinstance(i, Flower), elements), lambda i: i.pos.distance_to(player.pos)ます。

次のことは、効率、クリーンなコード、および単純さの観点から良い考えですか?それとも、これに適した方法、実装、またはデザインパターンはすでにありますか?

class Selector(object):
    def __init__(self, selection):
        self.s3l3ct1on = selection

    def __getattr__(self, name):
        return type(self)(getattr(el, name) for el in self.s3l3ct1on)

    def __iter__(self):
        return iter(self.s3l3ct1on)

    def filter(self, function):
        return type(self)(filter(function, self.s3l3ct1on))

そして、これはそれがどのように使われることができるかAです:(は2つの属性を持つ単なるクラスです:ab

>>> sel = [A(3, 4), A(0, 9), A('test', 3), A(4,22), A(3, 9)]
>>> Selector(sel)
<__main__.Selector object at 0x13b0a90>
>>> list(Selector(sel))
[<__main__.A object at 0x13b0fd0>,
 <__main__.A object at 0x13b0b50>,
 <__main__.A object at 0x13b0150>,
 <__main__.A object at 0x13b0710>,
 <__main__.A object at 0x13b06d0>]
>>> set(Selector(sel).a)
{0, 'test', 3, 4}
>>> list(Selector(sel).b)
[4, 9, 3, 22, 9]
>>> s = Selector(sel).b.filter(lambda i: i%2 == 0)
>>> list(s)
[4, 22]
4

2 に答える 2

1

あなたが言及するあらゆる種類の選択プロセスは、itertoolsイテレータの観点から定義することができます。以下はそれを形式化したものであり、さらに多くの種類をサポートするように簡単に拡張できます。使用する構文は非常に読みやすいようです。

パフォーマンステストは行いませんでしたが、関連するオーバーヘッドのほとんどすべてがコンストラクターメソッドにあるため、結果は競争力があると思います。ほんの少しでも速くなる可能性がある唯一のことは、その使用法を同等のitertoolsイテレータ関数に置き換えることです-したがって、この種の多くのことを行うことを期待している場合は、使用するのに有効な便利なツールのようです処理。

import itertools

class Selector(object):
    def __init__(self, iterable, **kwargs):
        if not kwargs:
            self.iterator = iterable
        elif len(kwargs) > 1:
            raise ValueError('only one selector type keyword allowed')
        else:
            selector, target = kwargs.items()[0]

            if selector == 'by_attr':
                self.iterator = itertools.imap(lambda obj: getattr(obj, target), iterable)
            elif selector == 'by_type':
                self.iterator = itertools.ifilter(lambda obj: isinstance(obj, target), 
                                                  iterable)
            elif selector == 'by_func':
                self.iterator = itertools.ifilter(target, iterable)
            else:
                raise ValueError('unknown selector type keyword')

    def __iter__(self):
        return self.iterator


if __name__ == '__main__':
    from selector import Selector

    class A(object):
        def __init__(self, a, b):
            self.a, self.b = a, b

    class Flower(object):
        def __init__(self, name):
            self.name = name

    sel = [A(3, 4), A(0, 9), A('test', 3), A(4,22), A(3, 9)]
    print list(Selector(sel, by_attr='a'))

    sel = [42, Flower('Buttercup'), [1,2,3,5,8], A(20, 13), Flower('Rose')]
    print list(Selector(sel, by_type=Flower))

    sel = [4, 9, 3, 22, 9]
    print list(Selector(sel, by_func=lambda i: i%2 == 0))
于 2013-02-14T02:25:55.503 に答える
1

簡単にするために、クラス自体を list のサブクラスにすることができます。

class Elements(list):
   def only_type(self, t):
       return Elements(i for i in self if isinstance(i, t))

   def get_nearest(self, who):
       return min(self, key=lambda x: x.pos.distance_to(who.pos))

el = Elements([Flower(), Person(), Flower(), Something()])

el.only_type(Flower).get_nearest(player)

と同じことSelector

于 2013-02-13T23:12:50.437 に答える