2012-01-11 12 views
6

私は、増加する整数を別の関数に渡す必要があるメソッドを持っています。自動インクリメンタル呼び出し可能?

私はそうのようにこれを行うことができます:

def foo(i): 
    print i 

def bar(): 

    class Incrementer(object): 
     def __init__(self, start=0): 
      self.i = start 

     def __get__(self): 
      j = self.i 
      self.i += 1 
      return j 

    number = Incrementer() 
    foo(number) 
    foo(number) 
    foo(number) 

は正しく0 1 2 ...を出力するが、私はこれを行うことの方がはるかに簡単(または内蔵)道を見下ろすてるような気が?

+1

コードが正常に機能していますか? '__get __()'メソッドは、ここでは起こっていないような新しいスタイルのクラスから属性を取得するときにのみ呼び出されます。 –

+0

うん、それは正常に動作します。あなたがそれを実行した場合にのみ動作するはずです: 'number = new Incrementer()'?何故ですか? –

+1

[あなたのコードは '0 1 2'を出力するとは思わない](http://ideone.com/kvCE1)。そして、私は 'number = new Incrementer()'について話しているわけではありません。ここでは混乱するようですが、Pythonには 'new'演算子はありません。私は[記述子](http://docs.python.org/reference/datamodel.html#descriptors)の呼び出しについて話しています。 –

答えて

14

itertools.count()試してみてください - それはあなたが必要な正確に何が行われます。一般的には

>>> c = itertools.count() 
>>> next(c) 
0 
>>> next(c) 
1 
>>> next(c) 
2 
+0

これはまさに私が探していたものです。ありがとう! –

7

、あなたは一つの関数の呼び出しと次の間で状態を保持する必要がある場合は、あなたが欲しいのは(オブジェクトのいずれかであるあなたの溶液)または発生器である。場合によっては、1つは他のものよりも簡単になりますが、実現方法にはが間違っているがありません(実装に問題があるようですが)。

スヴェンの提案、itertools.count()は、ジェネレータです。その実装は、このようなものです:

def count(c=itertools.count()): 
    return next(c) 
:今

def count(): 
    i = 0 
    while True: 
     yield i 
     i += 1 

あなたはそれがかなりnext(c)を行うに持つよりも、関数のように呼び出し可能になりたいと思った場合、あなたはそれを作ったラッパーを定義することができます

または必然的な1行のラムダ:次に

count = lambda c=itertools.count(): next(c) 

count()は、次の整数にあなたがそれを呼び出すたびに返します。もちろん

、あなたが呼び出し可能な関数をいくつでも作成することができるようにしたい場合は、自分のカウンターで、それぞれが、あなたはそのための工場書くことができます。

def counter(): 
    return lambda c=itertools.count(): next(c) 

はそれからだ。

c = counter() 
print c() # 0 
print c() # 1 
# etc 

これはまだオブジェクトよりも私にとっては簡単ですが、多くはそうではありません。状態やロジックが複雑になった場合は、オブジェクトのカプセル化が勝てる可能性があります。

+1

また、 'count = itertools.count().__ next__'、または' count = itertools.count()。next'をPython 2.6以降で使用します。 –

+1

@ F.J:第2の変種は2.7を含むすべての2.xバージョンに適用されます。 '__next __()'は3.xでのみ利用可能です。 –

関連する問題