클래스의 속성 얻기


106

클래스의 속성을 얻고 싶습니다.

class MyClass():
  a = "12"
  b = "34"

  def myfunc(self):
    return self.a

를 사용 MyClass.__dict__하면 속성 및 함수 목록과 __module__및 같은 함수도 제공 __doc__됩니다. 하지만 MyClass().__dict__나에게 빈 딕셔너리를 제공 I 명시 적으로 해당 인스턴스의 속성 값을 설정하지 않는 한.

위의 예에서 속성은 다음 a과 같습니다.b


답변:


123

검사 모듈을 사용해보십시오 . 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')]

... 더 복잡한 것은 특수 속성 이름 검사 또는 메타 클래스를 포함 할 수 있습니다.)


응 이거 대단해! :이 사용 attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))) print [a[0] for a in attributes if '_' not in a[0]]
모하메드 카 미스

2
속성이 포함되지 않습니다 like_this. 또한 의도적으로 수행했을 수있는 "비공개"속성을 피할 수 있습니다.
Matt Luongo

식에 : 안녕하세요, 저는 약간의 설명으로도 그 사랑 inspect.getmembers(MyClass, ..., MyClass클래스 또는 객체로 대체 될 수 있으며, 당신이 당신의 개체의 값 목록을 필요로하는 경우, 당신은 대체해야하는 MyClass개체 변수에 의해 (또는 self당신이 넣을 경우 이 표현은 def __repr__()나 같은 방법으로).
herve-guerin

나는 이것을 (Python3에서) 사용하여 ' dict '값 을 찾는 함수를 얻었습니다 . i = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))); z = [_[1] for _ in i if _[0] in '__dict__'][0]그리고 그것은 단지 z에서 키를 얻는 문제입니다.
double0darbo 2011

42
def props(cls):   
  return [i for i in cls.__dict__.keys() if i[:1] != '_']

properties = props(MyClass)

7
이 메소드 이름이 포함됩니다
lenhhoxung

10
확인하는 것이 더 명확 if not i.startswith('_')하지 않습니다 . 대신 if i[:1] != '_'?
Mikaelblomkvistsson 2011

2
참고 : 자식 클래스 (상 속됨)에 대해 이야기하면 .__dict__.keys()부모의 속성이 포함되지 않습니다.
vishes_shell

21

myfunc 이다 의 속성 MyClass. 다음과 같이 실행할 때 발견됩니다.

myinstance = MyClass()
myinstance.myfunc()

myinstance이름이 지정된 속성을 myfunc찾고, 하나를 찾지 못하고 myinstance, 인스턴스 인 것을보고 MyClass거기에서 찾습니다.

따라서에 대한 전체 속성 목록 MyClass은 다음과 같습니다.

>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']

(저는 클래스 멤버를 나열하는 빠르고 쉬운 방법으로 dir을 사용하고 있습니다. 프로덕션 코드가 아닌 탐색 적 방식으로 만 사용해야합니다.)

당신은 단지 특정 속성을 원하는 경우에 때문에, 당신은 몇 가지 기준을 사용하여이 목록을 필터링해야합니다 __doc__, __module__그리고 myfunc어떤 방법으로 특별하지 않은 사람들은 정확히 같은 방식으로,있는 거 특성을 a하고 b있습니다.

Matt와 Borealid가 참조하는 inspect 모듈을 사용한 적이 없지만 간단한 링크를 보면이 작업을 수행하는 데 도움이되는 테스트가있는 것처럼 보이지만 원하는대로 보이기 때문에 자체 조건 자 함수를 작성해야합니다. 대략 속성입니다 하지 않는 패스 isroutine테스트를하고 시작하고 두 개의 밑줄로 끝나지 않습니다.

또한 참고 : class MyClass():Python 2.7에서 사용하면 매우 오래된 구식 클래스를 사용하게됩니다. 매우 오래된 라이브러리와의 호환성을 위해 의도적으로 그렇게하지 않는 한, 대신 클래스를 class MyClass(object):. Python 3에는 "이전 스타일"클래스가 없으며이 동작이 기본값입니다. 그러나 newstyle 클래스를 사용하면 훨씬 더 자동으로 정의 된 속성을 얻을 수 있습니다 .

>>> 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']

6
하나에 의존 할 수 dir()" DIR은 ()에서 사용의 편의를 주로 공급되기 때문에 대화 형 프롬프트 그것이 이름의 엄격 또는 일관되게 정의 세트를 제공하려고보다 더 많은 이름의 흥미로운 세트를 제공하려고 하고, 그것의 상세한 동작은 릴리스에 따라 변경 될 수 있습니다 . "( 문서dir() 참조 ).
Tadeck

@Tadeck : 좋은 지적입니다. 나는 그것을 해결책으로 제안하기보다는 예시 적으로 사용하고 있었다. 왜냐하면 참조하는 것을 기반으로 속성을 쉽게 필터링 할 수 없기 때문이다. 그러나 나는 그것에 대해 더 명확하게해야합니다.

14

인스턴스 속성 만 가져 오는 것은 쉽습니다.
그러나 함수없이 클래스 속성 을 가져 오는 것은 좀 더 까다 롭습니다.

인스턴스 속성 만

인스턴스 속성 만 나열해야하는 경우
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

인스턴스 및 클래스 속성

함수없이 클래스 속성 도 얻으려면 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 self.__dict__.keys():
       if attribute[:2] != '__':
         value = getattr(self, 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

8

MyClass().__class__.__dict__

그러나 "올바른"방법은 inspect 모듈을 사용하는 것 입니다.


6
MyClass().__class__.__dict__==MyClass.__dict__
yak

5
@yak의 의견은 사실이 아닙니다. 클래스 속성과 인스턴스 속성의 차이점은 다음을 참조하세요. stackoverflow.com/questions/35805/…를 참조하십시오 .
sholsapp

@sholsapp 실제로 @yak이 맞습니다. 제공 한 링크에라고 표시되어 MyClass().__class__.__dict__ != MyClass().__dict__있지만 yak는 오른쪽에 괄호를 포함하지 않습니다.이 경우 올바른 경우
shadi

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()

목록 이해력 type(mc)대신 사용 MyClass하십시오. 하나의 동적에 속성 추가하는 경우, mc등을 mc.c = "42"사용하는 경우, 속성은 표시되지 않습니다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('__'))]

정말 깔끔한 솔루션.
Gitnik

2

비슷한 것이 지금까지 만들어 졌는지 여부는 모르겠지만 vars ()를 사용하여 멋진 속성 검색 기능을 만들었습니다. 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으로 꽤 방대한 텍스트 어드벤처를 개발 중이며 지금까지 내 Player 클래스에는 100 개 이상의 속성이 있습니다. 이 기능을 사용하여 확인해야하는 특정 속성을 검색합니다.


불행히도 vars ()는 클래스 속성을 반환하지 않습니다
user2682863 aug

내가 게시 한 코드를 실행 해 보셨습니까? Vars는 확실히 클래스 속성을 반환 할 수 있습니다. 그렇지 않은 방법의 예를 보여 주시겠습니까? 내 코드가 올바르지 않을 수 있습니다. 그러나 vars ()를 변수에 할당하고 해당 변수를 통한 키, 값 검색을 사용하면 클래스 속성을 반환 할 수 있습니다.
Corey Bailey

클래스 T : x = 1; t = T (); vars (t)
user2682863

제대로 보여 드리려면 제가 퇴근 할 때까지 기다려야합니다. 그러나 코드가 올바르지 않습니다. 클래스 객체는 __init __ (self)를 정의해야하고 x는 self.x = 1이어야합니다. 그런 다음 t = T ()를 할당하고 print (vars (t))를 사용하면 모든 클래스 속성의 사전이 표시됩니다.
Corey Bailey

아니요, 그것들은 클래스 속성이 아닌 인스턴스 속성입니다. 많은 하위 클래스는 절대 init를 호출하지 않습니다 . 내가 말했듯이 vars ()는 클래스 속성을 반환하지 않으므로 dir () 또는 inspect.getmembers ()를 사용해야합니다
user2682863

2

이것은 검사없이 수행 할 수 있습니다.

다음 수업을 들으십시오.

 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를 사용하십시오 .


2

Python 2 및 3, whitout 가져 오기, 주소로 객체 필터링

요약 :

필터링 된 객체 인 dict {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)}

반환 목록 [attribute_names] , 개체가 필터링되었습니다. 즉['a', 'b', 'c', 'd']

[k for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]

반환 목록 [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 문은 반환 True의 메모리 위치의 16 진수 표현이 경우 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 문서 는 id ()에 대해 말합니다.

객체의 "ID"를 반환합니다. 이는 수명 동안이 개체에 대해 고유하고 일정하게 보장되는 정수입니다. 수명이 겹치지 않는 두 개체는 동일한 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

  • 파이썬에서 2.X는 .iteritems()이상이 바람직하다.items()


1

나는 최근에이 질문과 비슷한 것을 알아 내야했기 때문에 앞으로 같은 상황에 직면 한 다른 사람들에게 도움이 될 배경 정보를 게시하고 싶었습니다.

다음은 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), 파이썬 먼저 확인 새 인스턴스의 DICT를 MyClass().__dict__['b']찾아 실패 b. 그런 다음 클래스 확인 MyClass.__dict__['b']및 발견을 b.

그래서 당신은 inspect 동일한 검색 프로세스를 에뮬레이트하기 위해 모듈 .


2
Scott-답변으로 게시 된 댓글은 삭제되어야합니다. 그렇지 않으면 그 안에 빠져들 것입니다. 그러나 솔루션에 대한 부분적인 대답 또는 "유용한 넛지"는 여전히 대답 입니다. 내가 귀하의 게시물을 어떻게 바꾸 었는지 볼 수 있습니다. 당신의 의도를 간직했으면 좋겠습니다. 그렇지 않은 경우 추가 로 모양을 편집 할 수 있습니다 . 건배!
Mogsdad

1

목록 이해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('_')]

1

클래스의 모든 속성 (메서드 아님)을 얻는 내 솔루션 (클래스에 속성 철자가 명확하게 표시된 적절하게 작성된 독 스트링이있는 경우) :

def get_class_attrs(cls):
    return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])

이 조각 cls.__dict__['__doc__']은 클래스의 독 스트링을 추출합니다.


1

속성을 나열해야하는 이유는 무엇입니까? 의미 상 당신의 클래스는 컬렉션 인 것 같습니다. 이 경우 enum을 사용하는 것이 좋습니다.

import enum

class myClass(enum.Enum):
     a = "12"
     b = "34"

속성을 나열 하시겠습니까? 이보다 쉬운 것은 없습니다.

for attr in myClass:
    print("Name / Value:", attr.name, attr.value)

1

속성을 "가져 오기"를 원하는 경우 매우 간단한 대답이 있습니다 . 이는 분명해야합니다. 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 모두에서 멋지게 작동합니다.

이러한 항목의 목록이 필요한 경우에도 inspect를 사용해야합니다.


1
그 대답은 너무 간단하고 정확해서 어떤 점수를받을 자격이 없으며 심지어 나쁜 점수를받을 자격이 있습니까? 오늘날에는 경제성과 단순성이 더 이상 성과를 내지 못하는 것 같습니다.
fralau

0

두 기능 :

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'}

0

다음은 내가 원하는 것입니다.

테스트 데이터

class Base:
    b = 'b'


class MyClass(Base):
    a = '12'

    def __init__(self, name):
        self.name = name

    @classmethod
    def c(cls):
        ...

    @property
    def p(self):
        return self.a

    def my_fun(self):
        return self.name
print([name for name, val in inspect.getmembers(MyClass) if not name.startswith('_') and not callable(val)])  # need `import inspect`
print([_ for _ in dir(MyClass) if not _.startswith('_') and not callable(getattr(MyClass, _))])
# both are equ: ['a', 'b', 'p']

my_instance = MyClass('c')
print([_ for _ in dir(my_instance) if not _.startswith('_') and not callable(getattr(my_instance, _))])
# ['a', 'b', 'name', 'p']

-2

나는 이것이 3 년 전이라는 것을 알고 있지만, 미래에이 질문을 받게 될 사람들을 위해, 나를 위해 :

class_name.attribute 

잘 작동합니다.


3
AttributeError가 발생하는 경우를 제외하고.
rady

항상 무엇인지 attribute미리 알지는 못합니다 .
Matt Luongo

-3

사용할 수 있습니다 MyClass.__attrs__. 해당 클래스의 모든 속성을 제공합니다. 더 이상은 없습니다.


AttributeError : 유형 오브젝트 'X'는 어떤 속성 '이 없습니다 바인드합니다 '
라마 잔 폴랏
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.