0

外部ファイルから読み取る連続ループのPythonファイルがあり、読み取っているさまざまなデータポイントがあり、各ポイント(m1.x)の場所をフィードするために呼び出しているクラス(fb)があります、m2.xなど...)ファイルは30秒ごとにループします。

使用しているインスタンスごとにリセットされない変数がループ内に必要です。ループ内で定義するとリセットされ、グローバル変数を使用すると複数の変数に使用できなくなります。

したがって、以下の例では、「test」はグローバル変数としてすべてのインスタンスに対して1つカウントされ、self.Xは各ループの後にリセットされます。どちらも私が必要なことをしません。スレッドを使用しようとしましたが、これにより、使用しているモジュールでさらに多くの問題が発生します。したがって、ループしているクラス内でリセットされないローカル変数を作成する方法について誰かがアイデアを持っているなら、それは素晴らしいことです。ありがとう。

test = 0  
s = sched.scheduler(time.time, time.sleep)

def loop1(sc): 
    class fb:
        def link(self):
            global test
            test = test + 1
            print test

            self.X = self.X + 1
            print self.X

    m1 = fb()

    m1.X = 1
    m1.link()

    m2 =fb()
    m2.X = 0
    m2.link()

    # Update loop every 10 second    
    sc.enter(10, 10, loop1, (sc,))


# end loop
s.enter(1, 1, loop1, (s,))
s.run()
4

3 に答える 3

1

毎回リセットされないローカル変数を作成することはできません。ローカル変数の要点は、それがローカルであるということです。したがって、ローカル変数にすることはできません。

loop1ただし、同じ変数をめぐって競合しない2 つの異なるスケジュールされた関数を使用できるようにする必要があるため、グローバル変数にすることもできません。

したがって、必要なことは、ループ インスタンス自体が変数をバインドできるものになるように再編成することです。これを行うには、2 つの基本的な方法があります。

まず、クラスを作成し、関数をインスタンス メソッドにして、インスタンス変数にアクセスできるようにするという従来の OO ソリューションがあります。このようなもの:

class Looper(object):
    def __init__(self):
        self.test = 0
    def loop1(self, sc):
        # same code as before, but with self.test instead of test

looper1 = Looper()
looper2 = Looper()
s.enter(1, 1, looper1.loop1, (s,))
s.enter(1, 1, looper2.loop1, (s,))

あるいは、クロージャーを作成する従来の FP ソリューションがあります。

def make_loop1():
    test = 0
    def loop1(sc):
        nonlocal test
        # same code as before, unchanged
    return loop1
looper1 = make_loop1()
looper2 = make_loop1()
s.enter(1, 1, looper1, (s,))
s.enter(1, 1, looper2, (s,))

そして、さまざまなハイブリッド ソリューションがあり、関数自体をオブジェクト指向オブジェクトとして扱う (たとえば、test関数の属性として割り当てる) か、変更可能な値を引数として渡すことによってクロージャを偽造するなどです。

于 2013-02-15T00:27:13.367 に答える
1

各ターンで作成されたインスタンスの数 (= self.X) や、プログラムの開始以降に作成されたインスタンスの累積数 (= test) ではなく、ループのターンをカウントするオブジェクトyが必要だと思います。

ループの各ターンで 1 だけインクリメントするオブジェクトyを取得する次のプログラムがあります。ターンの開始時にまったく新しいクラスを作成する必要があります。命令

fb = type('fb',(object,),{'__init__':initer,
                              'link':linker,
                              'CLASSIES':0})

このまったく新しいクラスの作成を行います。これは、作成されたクラスの表示によって証明されますprint 'id(fb) == %d' % id(fb)
。オブジェクトのアイデンティティは、オブジェクトがメモリ内にある場所です。同じ ID でない場合、同じオブジェクトではありません。

import sched,time

test = 0  
s = sched.scheduler(time.time, time.sleep)

Y = 2000

def initer(self):
    global test,Y
    if self.__class__.CLASSIES == 0:
        Y += 1
        self.__class__.CLASSIES += 1

def linker(self):
    global test,Y
    test = test + 1
    self.X = self.X + 1
    print 'Y == %d' % Y
    print 'test == %d     self.X == %d' % (test,self.X)


def loop1(sc):
    fb = type('fb',(object,),{'__init__':initer,
                              'link':linker,
                              'CLASSIES':0})
    print '--------'
    print 'id(fb) == %d' % id(fb)
    m1 = fb()
    m1.X = 0
    m1.link()
    print 
    m2 =fb()
    m2.X = 1
    m2.link()
    print 
    m3 =fb()
    m3.X = 2
    m3.link()
    print '--------'

    # Update loop every 10 second
    sc.enter(10, 10, loop1, (sc,))


# end loop
s.enter(1, 1, loop1, (s,))
s.run()

ディスプレイ

--------
id(fb) == 18976648
Y == 2001
test == 1     self.X == 1

Y == 2001
test == 2     self.X == 2

Y == 2001
test == 3     self.X == 3
--------
--------
id(fb) == 13818640
Y == 2002
test == 4     self.X == 1

Y == 2002
test == 5     self.X == 2

Y == 2002
test == 6     self.X == 3
--------
--------
id(fb) == 18970384
Y == 2003
test == 7     self.X == 1

Y == 2003
test == 8     self.X == 2

Y == 2003
test == 9     self.X == 3
--------
--------
id(fb) == 18970864
Y == 2004
test == 10     self.X == 1

Y == 2004
test == 11     self.X == 2

Y == 2004
test == 12     self.X == 3
--------
--------
id(fb) == 18971736
Y == 2005
test == 13     self.X == 1

Y == 2005
test == 14     self.X == 2

Y == 2005
test == 15     self.X == 3
--------
--------
id(fb) == 18957224
Y == 2006
test == 16     self.X == 1

Y == 2006
test == 17     self.X == 2

Y == 2006
test == 18     self.X == 3
--------
.
.
.
etc

上記の方法でのみ、この結果を得ることができました。次のコードを実行するとわかるように、各ターンの終わりに
削除するだけでは不十分です。fbそれはあなたのコードであり、いくつかの指示がYあり、表示されますid(fb)`` anid(fb)`` は、あるターンから別のターンまで同じままであることがわかります。

import sched,time

test = 0  
s = sched.scheduler(time.time, time.sleep)

Y = 2000

def loop1(sc):
    class fb:
        def link(self):
            global test,Y
            test = test + 1
            self.X = self.X + 1
            print 'Y == %d' % Y
            print 'test == %d     self.X == %d' % (test,self.X)
    print 'id(fb) == %d' % id(fb)
    print '--------'
    m1 = fb()
    m1.X = 0
    m1.link()
    print 
    m2 =fb()
    m2.X = 1
    m2.link()
    print 
    m3 =fb()
    m3.X = 0
    m3.link()
    print '--------'
    del fb

    # Update loop every 10 second
    sc.enter(10, 10, loop1, (sc,))


# end loop
s.enter(1, 1, loop1, (s,))
s.run()

あなたのコードが思い通りに動かない理由は、私が本当に理解している限りでは、クラスを定義するスクリプトの部分が「クラスの定義」と呼ばれているためです (信じられないですね。 ) であり、インタープリターがこのクラス ブロックを初めて渡すときに、それを実行します。
「クラスの定義」を実行すると、クラスであるオブジェクトが作成されます。クラスが作成されるとすぐに、インタープリターがクラスのコードブロック (= クラス定義) を再度渡す場合、「定義」は再実行されません。
ここでも、あいまいな言葉があります。「定義」は、「クラスを定義するスクリプト内のテキスト ブロック」または「
「クラスの定義」に使用した意味は、ドキュメントで使用されているものです。

関数定義 (def ステートメント) のようなクラス定義は、効果を得る前に実行する必要があります。(おそらく、if ステートメントの分岐または関数内にクラス定義を配置できます。)

http://docs.python.org/2/tutorial/classes.html#class-definition-syntax

最後に、私が言いたいのは、あなたのコードでは、「クラス fb の定義」が 1 回だけ実行されるということです。その後、常に同じクラスがモデル化クラスであり、ループの順番を繰り返します。

于 2013-02-15T02:03:02.973 に答える
-1

私は以前にこれを行ったことがあります...モジュールを作成するか、それに慣れている場合は __ init__.py を使用してください

__ init__.py または where.py 内

from somepackage.some_module import my_function
my_obj = my_function()

your_awesome_module.py では、オブジェクトを使用できます

from path.to.wherever import my_obj
# Do stuff with my_obj
于 2013-02-15T00:31:30.080 に答える