クラスの属性を取得したい、と言う:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
MyClass.__dict__
を使用すると、属性と関数、さらに__module__
や__doc__
などの関数のリストが表示されます。 MyClass().__dict__
は、そのインスタンスの属性値を明示的に設定しない限り、空の辞書を提供します。
属性が欲しいだけです。上の例ではa
とb
になります。
inspect モジュールを試してください。 getmembers
およびさまざまなテストが役立つはずです。
編集:
例えば、
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
('__dict__',
<dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'a': '34',
'b': '12',
'myfunc': <function __main__.myfunc>}>),
('__doc__', None),
('__module__', '__main__'),
('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
('a', '34'),
('b', '12')]
今、特別なメソッドと属性が私の神経になります-それらはいくつかの方法で処理できますが、最も簡単なのは名前に基づいてフィルタリングすることです。
>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]
...さらに複雑なものには、特別な属性名チェックやメタクラスを含めることができます;)
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)
myfunc
isMyClass
の属性。実行すると、次のようになります。
myinstance = MyClass()
myinstance.myfunc()
myinstance
という名前の属性をmyfunc
という名前で探しますが、見つけられません。myinstance
がMyClass
のインスタンスであることがわかり、そこで検索されます。
したがって、MyClass
の属性のcompleteリストは次のとおりです。
>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']
(クラスのメンバーをリストするための迅速かつ簡単な方法としてdirを使用していることに注意してください:運用コードではなく探索的方法でのみ使用する必要があります)
特定の属性のみが必要な場合は、__doc__
、__module__
、およびmyfunc
は属性ではないため、何らかの条件を使用してこのリストをフィルターする必要があります。 a
およびb
とまったく同じ方法で。
MattとBorealidによって参照される検査モジュールを使用したことはありませんが、簡単なリンクからは、これを行うのに役立つテストがあるように見えますが、あなたが望むように見えるので、独自の述語関数を書く必要がありますおおよそ、しない属性はisroutine
テストに合格し、2つのアンダースコアで開始および終了しない属性です。
また、注意:Python 2.7でclass MyClass():
を使用することにより、非常に古い古いスタイルのクラスを使用していることになります。非常に古いライブラリとの互換性のために意図的にそうしているのでない限り、代わりにクラスをclass MyClass(object):
として定義する必要があります。 Python 3には「古いスタイル」のクラスはなく、この動作がデフォルトです。ただし、newstyleクラスを使用すると、lotより自動的に定義された属性が得られます。
>>> class MyClass(object):
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc']
MyClass().__class__.__dict__
ただし、これを行うための「正しい」方法は inspect module です。
インスタンス属性のみを取得するのは簡単です。
しかし、関数なしでclass属性も取得するのは少し注意が必要です。
リストインスタンス属性のみが必要な場合は、for attribute, value in my_instance
. __dict__
..items()
>>> from __future__ import (absolute_import, division, print_function)
>>> class MyClass(object):
... def __init__(self):
... self.a = 2
... self.b = 3
... def print_instance_attributes(self):
... for attribute, value in self.__dict__.items():
... print(attribute, '=', value)
...
>>> my_instance = MyClass()
>>> my_instance.print_instance_attributes()
a = 2
b = 3
>>> for attribute, value in my_instance.__dict__.items():
... print(attribute, '=', value)
...
a = 2
b = 3
関数なしでclass属性も取得するには、 callable()
を使用するのがコツです。
しかし 静的メソッド は 常にcallable
とは限りません !
したがって、callable(value)
を使用する代わりにcallable
( getattr
(MyClass, attribute))
)
from __future__ import (absolute_import, division, print_function)
class MyClass(object):
a = "12"
b = "34" # class attributes
def __init__(self, c, d):
self.c = c
self.d = d # instance attributes
@staticmethod
def mystatic(): # static method
return MyClass.b
def myfunc(self): # non-static method
return self.a
def print_instance_attributes(self):
print('[instance attributes]')
for attribute, value in self.__dict__.items():
print(attribute, '=', value)
def print_class_attributes(self):
print('[class attributes]')
for attribute in MyClass.__dict__.keys():
if attribute[:2] != '__':
value = getattr(MyClass, attribute)
if not callable(value):
print(attribute, '=', value)
v = MyClass(4,2)
v.print_class_attributes()
v.print_instance_attributes()
注:print_class_attributes()
は @staticmethod
である必要があります
しかし、この愚かで単純な例ではありません。
$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2
$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2
import re
class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
attributes = [a for a, v in MyClass.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
次のようなMyClassのインスタンスの場合
mc = MyClass()
リスト内包表記のMyClass
の代わりにtype(mc)
を使用します。ただし、mc.c = "42"
などのmc
に属性を動的に追加する場合、この戦略でtype(mc)
を使用すると属性は表示されません。元のクラスの属性のみを提供します。
クラスインスタンスの完全な辞書を取得するには、type(mc).__dict__
とmc.__dict__
の辞書を結合する必要があります。
mc = MyClass()
mc.c = "42"
# Python 3.5
combined_dict = {**type(mc).__dict__, **mc.__dict__}
# Or Python < 3.5
def dict_union(d1, d2):
z = d1.copy()
z.update(d2)
return z
combined_dict = dict_union(type(mc).__dict__, mc.__dict__)
attributes = [a for a, v in combined_dict.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
今までに似たようなことが行われたかどうかはわかりませんが、vars()を使用してNice属性検索関数を作成しました。 vars()は、通過するクラスの属性の辞書を作成します。
class Player():
def __init__(self):
self.name = 'Bob'
self.age = 36
self.gender = 'Male'
s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)
#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
ask = input("What Attribute?>: ")
for key, value in s.items():
if key == ask:
print("self.{} = {}".format(key, value))
break
else:
print("Couldn't find an attribute for self.{}".format(ask))
Pythonで非常に大規模なText Adventureを開発しています。これまでのPlayerクラスには100を超える属性があります。これを使用して、必要な特定の属性を検索します。
これは検査せずに行うことができると思います。
次のクラスを受講してください。
class Test:
a = 1
b = 2
def __init__(self):
self.c = 42
@staticmethod
def toto():
return "toto"
def test(self):
return "test"
メンバーとそのタイプを見る:
t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]
...与えるもの:
[('__doc__', 'NoneType'),
('__init__', 'instancemethod'),
('__module__', 'str'),
('a', 'int'),
('b', 'int'),
('c', 'int'),
('test', 'instancemethod'),
('toto', 'function')]
したがって、変数のみを出力するには、結果をタイプ、および「__」で始まらない名前でフィルタリングする必要があります。例えば。
filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)
[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result
それでおしまい。
注:Python 3を使用している場合、イテレータをリストに変換します。
より堅牢な方法が必要な場合は、 inspect を使用します。
クラスのすべての属性(メソッドではない)を取得するための私のソリューション(クラスに、属性が明確に記述された適切に記述されたdocstringがある場合):
def get_class_attrs(cls):
return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])
この部分cls.__dict__['__doc__']
は、クラスのdocstringを抽出します。
私は最近、この質問に似た何かを理解する必要があったので、将来同じものに直面している他の人に役立つかもしれない背景情報を投稿したいと思いました。
Python( https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy から)での動作は次のとおりです。
MyClass
はクラスオブジェクト、MyClass()
はクラスオブジェクトのインスタンスです。インスタンスの__dict__
は、そのインスタンスに固有の属性とメソッドのみを保持します(例:self.somethings
)。属性またはメソッドがクラスの一部である場合、それはクラスの__dict__
にあります。 MyClass().__dict__
を実行すると、MyClass
のインスタンスが作成され、クラス属性以外に属性やメソッドが作成されないため、空の__dict__
したがって、print(MyClass().b)
と言うと、Pythonは最初に新しいインスタンスの辞書MyClass().__dict__['b']
をチェックし、b
を見つけられません。次に、クラスMyClass.__dict__['b']
をチェックし、b
を見つけます。
そのため、同じ検索プロセスをエミュレートするには、inspect
モジュールが必要です。
リスト内包表記でdir()
を使用して、属性名を取得できます。
names = [p for p in dir(myobj) if not p.startswith('_')]
getattr()
を使用して、属性自体を取得します。
attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]
MyClass.__attrs__
を使用できます。そのクラスのすべての属性を提供するだけです。これ以上何もない。
Returndict {attribute_name:attribute_value}、フィルタリングされたオブジェクト。すなわち{'a': 1, 'b': (2, 2), 'c': [3, 3]}
{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}
Returnlist [attribute_names](、フィルタリングされたオブジェクト。すなわち['a', 'b', 'c', 'd']
[k for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]
Returnlist [attribute_values](、フィルタリングされたオブジェクト。すなわち[1, (2, 2), [3, 3], {4: 4}]
[val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]
if
条件を削除します。 {'a': 1, 'c': [3, 3], 'b': (2, 2), 'e': <function <lambda> at 0x7fc8a870fd70>, 'd': {4: 4}, 'f': <object object at 0x7fc8abe130e0>}
を返します
{k: val for k, val in self.__dict__.items()}
__repr__
のデフォルト実装がオーバーライドされない限りif
ステートメントは、16進数の場合True
を返します。 val
のメモリ内の場所の表現は、__repr__
戻り文字列にあります。
__repr__
のデフォルトの実装に関しては、有用な この回答 を見つけることができます。要するに:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
Wichは次のような文字列を返します。
<__main__.Bar object at 0x7f3373be5998>
各要素のメモリ内の場所は、id()
メソッドを介して取得されます。
Python Docs はid()について述べています:
オブジェクトの「アイデンティティ」を返します。これは、このオブジェクトの存続期間中に一意で一定であることが保証されている整数です。オーバーラップしないライフタイムを持つ2つのオブジェクトは、同じid()値を持つ場合があります。
CPython実装の詳細:これは、メモリ内のオブジェクトのアドレスです。
class Bar:
def __init__(self):
self.a = 1
self.b = (2, 2)
self.c = [3, 3]
self.d = {4: 4}
self.e = lambda: "5"
self.f = object()
#__str__ or __repr__ as you prefer
def __str__(self):
return "{}".format(
# Solution in Short Number 1
{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}
)
# Main
print(Bar())
出力:
{'a': 1, 'c': [3, 3], 'b': (2, 2), 'd': {4: 4}}
注:
Python 2.7.13
およびPython 3.5.3
でテスト済み
Python 2.x .iteritems()
は.items()
よりも優先されます
非常に簡単な答えがあります。これは明らかなはずです:getattr
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> getattr(MyClass, 'a')
'12'
>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>
Python 2.7とPython 3.xの両方でうまく機能します。
これらのアイテムのリストが必要な場合は、検査を使用する必要があります。
2つの機能:
def get_class_attr(Cls) -> []:
import re
return [a for a, v in Cls.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
def get_class_attr_val(cls):
attr = get_class_attr(type(cls))
attr_dict = {}
for a in attr:
attr_dict[a] = getattr(cls, a)
return attr_dict
つかいます:
>>> class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> m = MyClass()
>>> get_class_attr_val(m)
{'a': '12', 'b': '34'}