in演算子

in演算子、便利ですよね。こんな感じです。

a = [ 1, 2, 3 ]
print 2 in a        # True

C#なら、

var a = new int[] { 1, 2, 3 };
Console.WriteLine(a.Contains(2));   // True

ちょっとうっとうしい。C++に至っては、

int a[] = { 1, 2, 3 };
std::cout << (std::find(a, a + 3, 2) != a + 3) << std::endl;    // 1

これですからね。

in演算子はこのようにsetや辞書やリストで使えますが、実はgenerator式などのiteratorでも使えるんですね。昨日気づきました。

g = (n * n for n in xrange(10))
print 9 in g    # True

このあと、

print 16 in g   # True
print 4 in g    # False

とすると、4はもう生成した後で、25, 36, …と生成されるのでFalseです。念のため、

g = (n * n for n in xrange(10))
print 23 in g   # False

となります。

詳しくは、ドキュメントに書いてあります。__contains__()か__iter__()か__getitems__()が定義されていればin演算子が使えるんですね。iteratorには__iter__()メソッドがあるからin演算子が使えるわけです。__getitems__()についてもオレオレコンテナを作って試してみましょう。

class MyList:
    def __init__(self, a):
        self.a = a
    
    def __getitem__(self, k):
        return self.a[k]

a = MyList([ 1, 3, 5 ])
print 2 in a    # False
print 3 in a    # True

kを0から3までなめています。