web-dev-qa-db-ja.com

Python-オブジェクトが特定のモジュールのクラスのインスタンスであるかどうかを確認します

オブジェクトが特定のモジュールのクラスのインスタンスであるかどうかを確認する方法が必要です。

そのモジュールからすべてのクラスを明示的にインポートし、タプルでチェックすることでそれができることを私は知っています。

from my_module import ClassOne, ClassTwo

>>> isinstance(my_obj, (ClassOne, ClassTwo))
True

しかし実際には、インポート元のモジュールには大量のクラスが含まれており、それらすべてを明示的にインポートし、それらを使用して巨大なタプルを構築し、それに対してタイプチェックを行うのは不必要に冗長に思えます。私はこれを避けるためにいくつかのことを試みました:

import my_module

# Test my_obj against the module itself
>>> isinstance(my_obj, my_module)
TypeError: isinstance() arg 2 must be a class, type, or Tuple of classes and types

# Try to test against a wildcard attribute on my_module
>>> isinstance(my_obj, my_module.*)
SyntaxError: invalid syntax

#Try to build a Tuple of clases with iteration to check against
>>> for klass in my_module:
TypeError: 'module' object is not iterable

タプルで明示的に名前を付けずに、my_module内のすべてのクラスに対してタイプチェックを行う方法はありますか?

オプションの背景情報:
私は自分の問題に取り組むためのより良い方法を見落としているかもしれません-あなたが疑問に思っているなら、これが状況です:

Google AppEngineアプリからRackspaceでホストしているアプリにデータをエクスポートしています。 pickleを使用してデータをシリアル化し、HTTPリクエストを使用してRackspaceサーバーに送信します。

Google App Engineデータベースの一部のデータは、google.appengine.api.datastore_typesからインポートされたGAE固有のデータ型です。これらのデータ型のいずれかがRackspaceサーバーにネットワーク経由で送信されると、Rackspaceアプリに必要なGAEライブラリがないため、エラーが発生します。そのため、GAEを終了する途中で、送信オブジェクトのいずれかにgoogle.appengine.api.datastore_typesのタイプがあるかどうかを確認しています。もしそうなら、私はそれらを組み込みのデータ型に変換するか、オブジェクトからフィールドを削除します。

23
Clay Wardell

inspect.getmembers を使用して、モジュール内のすべてのクラスを取得できます。

inspect.getmembers(my_module,inspect.isclass)

これにより、名前とクラスのペアのリストが返されます。あなたはただクラスが欲しいだけです:

my_module_classes = Tuple(x[1] for x in inspect.getmembers(my_module,inspect.isclass))

この回答を最初に書いたときに見落としていたのは、クラスの__module__属性をチェックする機能です。 __module__が期待どおりであるかどうかを確認することで回避できる場合があります。

from somewhere import module

if getattr(obj, '__module__', None) == module.__name__:
    # obj is from module.

これは、クラス名の大きなリストに対してisinstanceチェックするよりも安価である可能性があります。

14
mgilson

私は@mgilsonの簡単な解決策を使用しました:

from somewhere import module

if getattr(obj, '__module__', None) == module.__name__:
    # obj is from module.

モジュールのツリーがあり、それが基本モジュールからのものであることを確認したい場合は、次のことを行う必要があることに気づきました。

from somewhere import module

if getattr(obj, '__module__', None).split('.')[0] == module.__name__:
    # obj is from module.

ただし、objectが組み込みのものである場合は例外が発生するため、次のようにします。

from somewhere import module

module_tree = getattr(obj, '__module__', None)
parent = module_tree.split('.')[0] if module_tree else None

if parent == module.__name__:
    # obj is from module.
2