7

以下に定義されている 2 つの python ファイルがあるとします。1 つは一般的なパッケージ ( class2) で、もう 1 つは特定のオーバーライドを行い、実行可能ファイルとして機能するとします ( class1)。

class1.py:

#!/usr/bin/python
class Test(object):
    pass

class Verificator():
    def check(self, myObject):
        if not isinstance( myObject, Test ):
            print "%s is no instance of %s" % (type(myObject),Test)
        else:
            print "OK!"

if __name__ == '__main__':
    from class2 import getTest

    v = Verificator()
    t = Test()
    v.check(t)
    s = getTest()
    v.check(s)

class2.py:

from class1 import Test
def getTest():
    return Test()

何が起こるかというと、最初のチェックは OK で、2 番目のチェックは失敗します。その理由は、tisと のチェックですが、結局のところ、同じクラスですよね?__main__.Testsclass1.Testv.check()__main__.Test

v.check()オブジェクトも受け入れるように書く方法class1.Test、またはこれを解決する他の方法はありますか?

4

3 に答える 3

7

他の場所からインポートする予定がある場合はclass1.py、最上位コード (if __name__ == '__main__': ...を完全に別のファイルに移動します。そうすることで、メイン ファイルとclass2作業の両方を同じclass1.Testクラスで行うことができます。

他のほとんどのことを行うと、ワームの缶が開きます。isinstanceに切り替えることで差し迫った問題を回避できますが、Python プロセスには1 つしかないはずのクラスがtype(myObject).__name__ == ...2 つ含まれているという事実が残ります。Testそうでなければ見分けがつかないクラスは、お互いのことを何も知らず、お互いのissubclassテストに失敗します。これにより、診断が困難なバグがさらに先に進むことが実質的に保証されます。

編集
別のオプションはclass1、答えのように、メインとして実行するときにクラスを明示的にインポートすることです。さらに一歩進んで、クラスが double で定義されていないことを確認することをお勧めします。たとえば、if __name__ == '__main__'ブロックをファイルの先頭sys.exit(0)に移動し、次のように終了できます。

if __name__ == '__main__':
    import class1, class2
    ... use only the public API with module prefixes ...
    sys.exit(0)

# the rest of the module follows here
于 2013-03-01T14:49:14.677 に答える
1

ヒントをありがとう。最終的に正しい方向に実験するのに役立ちました。このおもちゃのモデルで見つけた解決策は、インポートを使用して名前空間の問題を修正することです。user4815162342 さんが指摘した問題を除外するために、class1 に別のクラスを追加しました。class1.py の次のコードは、私が望むことを行うように見えます:

#!/usr/bin/python
class Test(object):
    pass

class Toast(object):
    pass

class Verificator():
    def check(self, myObject):
        if not isinstance( myObject, Test ):
            print "NOPE: %s is no instance of %s" % (type(myObject),Test)
        else:
            print "OK: %s is instance of %s" % (type(myObject),Test)

if __name__ == '__main__':
    from class2 import getTest
    from class1 import Test, Toast

    v = Verificator()
    t = Test()
    v.check(t)
    t = getTest()
    v.check(t)
    t = Toast()
    v.check(t)
于 2013-03-01T16:57:42.410 に答える
-2

関数を使用できますtype()(実際、この呼び出しはかなり一般的です!):

#!/usr/bin/python
class Test(object):
    pass

class Verificator():
    def check(self, myObject):
        if not isinstance( type(myObject), type(Test) ):
            print "%s is no instance of %s" % (type(myObject),Test)
        else:
            print "OK!"

if __name__ == '__main__':
    from class2 import getTest

    v = Verificator()
    t = Test()
    v.check(t)
    s = getTest()
    v.check(s)

おそらく悪い解決策:

if not isinstance( myObject.__class__, Test.__class__ ):  # Use __class__ here.

もちろんそれらは同等ですが、どうしても必要な場合を除き、2 つのアンダースコア メンバーを使用する必要があるのは悪い形式と見なされます。ただし、それらの存在を知ることは価値があるため、これを回答に含めた理由です。

私の知る限り、これが発生することに注意してください。実行するpython class1.pyと、class1.py にはモジュールがないためです。そのため、python はすべてを__main__モジュールに配置します。これ、他のスクリプトからインポートする場合には当てはまりません。そのため、何かを__main__モジュールの一部として見ることは、実際には特殊なケースです!

于 2013-03-01T14:31:28.667 に答える