回答:
次のプログラムで
#! /usr/bin/env python
import foo
def fullname(o):
# o.__module__ + "." + o.__class__.__qualname__ is an example in
# this context of H.L. Mencken's "neat, plausible, and wrong."
# Python makes no guarantees as to whether the __module__ special
# attribute is defined, so we take a more circumspect approach.
# Alas, the module name is explicitly excluded from __qualname__
# in Python 3.
module = o.__class__.__module__
if module is None or module == str.__class__.__module__:
return o.__class__.__name__ # Avoid reporting __builtin__
else:
return module + '.' + o.__class__.__name__
bar = foo.Bar()
print fullname(bar)
そして、Bar
のように定義
class Bar(object):
def __init__(self, v=42):
self.val = v
出力は
$ ./prog.py
foo.Bar
o.__class__.__module__
これまでとは異なりo.__module__
ますか?
".".join([o.__module__, o.__name__])
はPython3 を強くお勧めします
AttributeError: 'AttributeError' object has no attribute '__module__'
提供された回答は、ネストされたクラスを扱いません。Python 3.3(PEP 3155)までは利用できませんが、実際__qualname__
にはクラスを使用する必要があります。最終的に(3.4?PEP 395)、__qualname__
モジュールの名前が変更された場合(つまり、モジュールの名前がに変更された場合)を処理するモジュールにも存在します__main__
。
Type.__module__ + '.' + Type.__qualname__
。
__qualname__
、クラス名にのみ解決されます
次のinspect
ような機能を持つモジュールの使用を検討してくださいgetmodule
。
>>>import inspect
>>>import xml.etree.ElementTree
>>>et = xml.etree.ElementTree.ElementTree()
>>>inspect.getmodule(et)
<module 'xml.etree.ElementTree' from
'D:\tools\python2.5.2\lib\xml\etree\ElementTree.pyc'>
inspect.getmodule()
完全修飾クラス名ではなく、モジュールオブジェクトを返します。実際、このinspect
モジュールは、この質問に実際に対処する機能を提供していません。この答えは答えではありません。</facepalm>
以下は、Greg Baconの優れた回答に基づくものですが、追加のチェックがいくつかあります。
__module__
ことができますNone
(ドキュメントによる)、また、同様にタイプのためにstr
それができる__builtin__
(あなたがログに表示される場合、または何でもないかもしれません)。次のチェックでは、これらの可能性の両方をチェックします。
def fullname(o):
module = o.__class__.__module__
if module is None or module == str.__class__.__module__:
return o.__class__.__name__
return module + '.' + o.__class__.__name__
(を確認するより良い方法があるかもしれません__builtin__
。上記はstrが常に利用可能であり、そのモジュールが常にであるという事実に依存しています__builtin__
)
python3.7の場合:
".".join([obj.__module__, obj.__name__])
取得:
package.subpackage.ClassName
obj
オブジェクトインスタンスではなくクラスである必要があることに注意してください。
一部の人々(たとえば、https://stackoverflow.com/a/16763814/5766934)__qualname__
は、それよりも優れていると主張しています__name__
。違いを示す例を次に示します。
$ cat dummy.py
class One:
class Two:
pass
$ python3.6
>>> import dummy
>>> print(dummy.One)
<class 'dummy.One'>
>>> print(dummy.One.Two)
<class 'dummy.One.Two'>
>>> def full_name_with_name(klass):
... return f'{klass.__module__}.{klass.__name__}'
>>> def full_name_with_qualname(klass):
... return f'{klass.__module__}.{klass.__qualname__}'
>>> print(full_name_with_name(dummy.One)) # Correct
dummy.One
>>> print(full_name_with_name(dummy.One.Two)) # Wrong
dummy.Two
>>> print(full_name_with_qualname(dummy.One)) # Correct
dummy.One
>>> print(full_name_with_qualname(dummy.One.Two)) # Correct
dummy.One.Two
ビルドインでも正しく機能します:
>>> print(full_name_with_qualname(print))
builtins.print
>>> import builtins
>>> builtins.print
<built-in function print>
このトピックの目的は完全修飾名を取得することであるため、同じパッケージ内に存在するメインモジュールと共に相対インポートを使用するときに発生する落とし穴があります。例えば、以下のモジュール設定で:
$ cat /tmp/fqname/foo/__init__.py
$ cat /tmp/fqname/foo/bar.py
from baz import Baz
print Baz.__module__
$ cat /tmp/fqname/foo/baz.py
class Baz: pass
$ cat /tmp/fqname/main.py
import foo.bar
from foo.baz import Baz
print Baz.__module__
$ cat /tmp/fqname/foo/hum.py
import bar
import foo.bar
同じモジュールを別の方法でインポートした結果を示す出力は次のとおりです。
$ export PYTHONPATH=/tmp/fqname
$ python /tmp/fqname/main.py
foo.baz
foo.baz
$ python /tmp/fqname/foo/bar.py
baz
$ python /tmp/fqname/foo/hum.py
baz
foo.baz
humが相対パスを使用してbarをインポートする場合、barはBaz.__module__
単に「baz」と見なされますが、フルネームを使用する2番目のインポートでは、barは「foo.baz」と同じように見なされます。
完全修飾名をどこかに永続化している場合は、それらのクラスの相対インポートを回避することをお勧めします。