클래스의 속성을 가져오는 중
클래스의 속성을 가져옵니다.
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
용사를 MyClass.__dict__함수의 는 속과함수목제심공다지같제함다공니합수도은음과어성고하록과 같은 기능도 제공합니다.__module__그리고.__doc__.하는 동안에MyClass().__dict__해당 인스턴스의 특성 값을 명시적으로 설정하지 않는 한 빈 딕트를 제공합니다.
위의예다같음은속원성합다니을과에서다:▁be원니▁i합,.a그리고.b
검사 모듈을 사용해 보십시오. 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)
인스턴스 속성만 가져오는 것은 쉽습니다.
그러나 기능 없이 클래스 속성을 얻는 것은 조금 더 까다롭습니다.
인스턴스 속성만
인스턴스 특성만 나열해야 하는 경우 다음을 사용합니다.
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(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()그래야 합니다
하지만 이 멍청하고 단순한 예에서는 그렇지 않습니다.
python2에 대한 결과
$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2
python3에 대한 동일한 결과
$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2
myfunc 의 속성입니다.MyClass이렇게 실행하면 검색됩니다.
myinstance = MyClass()
myinstance.myfunc()
은 서속찾다니습을성에 있는 .myinstance이름 지어진myfunc하나를 못찾어요, 세요보겠을 .myinstance는 의예니다의 입니다.MyClass위에서 찾아봅니다.
따라서 전체 속성 목록은 다음 속성 목록입니다.MyClass다음과 같습니다.
>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']
(저는 dir를 클래스 멤버를 빠르고 쉽게 나열하는 방법으로 사용하고 있습니다. dir는 탐색적인 방식으로만 사용해야 하며, 프로덕션 코드에서는 사용하지 않아야 합니다.)
에는 몇 조건을 하여 이 다음과 같이 필터링해야 합니다.__doc__,__module__,그리고.myfunc어떤 식으로든 특별하지 않습니다. 그들은 정확히 같은 방식으로 속성입니다.a그리고.b아레.
나는 Matt와 Borealid가 언급한 검사 모듈을 사용한 적이 없지만 간단한 링크를 보면 이를 수행하는 데 도움이 되는 테스트가 있는 것처럼 보이지만, 당신이 원하는 것은 대략 통과하지 못하는 속성인 것처럼 보이기 때문에 당신은 자신만의 술어 함수를 작성해야 합니다.isroutine테스트하고 두 개의 밑줄로 시작하고 끝나지 않습니다.
참고: 사방법을 합니다.class MyClass():Python 2.7에서는 구식 클래스를 사용하고 있습니다.을 위해 으로 그렇게 것이 , 를 극로오래라리호위그의로으하한렇않게,클를다정합야다니해의같이음과대신스도로 .class MyClass(object):Python 3에는 "old-style" 클래스가 없으며 이 동작이 기본값입니다.그러나 새 스타일 클래스를 사용하면 훨씬 더 자동으로 정의된 속성을 얻을 수 있습니다.
>>> 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__
그러나 "옳은" 방법은 검사 모듈을 통해 수행하는 것이었습니다.
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"용▁won를 사용하면 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('__'))]
Python 2 & 3, 화이트아웃 가져오기, 주소별로 개체 필터링
간단히 말해 솔루션:
{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()}
긴 해결책
의 기본 구현이 재정의되지 않는 한if는 문이반니다됩을 합니다.True 약 기 억 진 위 표 치 현 만 16수 의를 .val에 있습니다.__repr__리턴 스트링
의 기본 __repr__당신은 이 대답을 유용하게 찾을 수 있습니다.간단히 말해서:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
다음과 같은 문자열을 반환합니다.
<__main__.Bar object at 0x7f3373be5998>
각 요소의 메모리에 있는 위치는 다음을 통해 얻습니다.id()방법.
Python Docs는 id()에 대해 다음과 같이 말합니다.
개체의 "아이덴티티"를 반환합니다.이 정수는 개체의 수명 동안 고유하고 일정하도록 보장되는 정수입니다.수명이 겹치지 않는 두 개체의 id() 값이 같을 수 있습니다.
Cython 구현 세부 정보:메모리에 있는 개체의 주소입니다.
직접 해보세요.
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.13Python 및썬이3.5.32 Python 2.
.iteritems()보선는되보다.items()
만약 당신이 속성을 "얻고" 싶다면, 매우 간단한 답이 있는데, 이것은 명백해야 합니다: gettr.
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 모두에서 멋지게 작동합니다.
이러한 항목의 목록을 원하는 경우에도 검사를 사용해야 합니다.
지금쯤 비슷한 것이 만들어졌는지는 모르겠지만, 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에서 상당히 방대한 텍스트 어드벤처를 개발하고 있습니다. 지금까지 제 플레이어 클래스는 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을 사용하는 경우 반복기를 목록으로 변환합니다.
보다 강력한 방법을 사용하려면 검사를 사용합니다.
저는 최근에 이 질문과 비슷한 것을 알아내야 했기 때문에, 미래에 같은 문제에 직면한 다른 사람들에게 도움이 될 수 있는 몇 가지 배경 정보를 올리고 싶었습니다.
Python에서 작동하는 방법은 다음과 같습니다(https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy) :
MyClass개체입니다.MyClass()클래스 개체의 인스턴스입니다.사의__dict__인스턴스와 및 해인 스고예특및보메유니다합만드서성에유한턴스당예(:▁specific▁only다니▁attrib합:self.somethings에 .__dict__을 할 때는.MyClass().__dict__ 예MyClass클래스 속성 외에 속성이나 메서드가 없이 생성되므로 비어 있습니다.__dict__
그래서 만약 당신이print(MyClass().b) 새의 dict 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('_')]
클래스의 모든 속성(메소드가 아닌)을 가져오는 솔루션(클래스에 속성의 철자가 명확한 문서 문자열이 있는 경우):
def get_class_attrs(cls):
return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])
작품은 이품작.cls.__dict__['__doc__']클래스의 문서 문자열을 추출합니다.
속성을 나열해야 하는 이유는 무엇입니까?의미론적으로 클래스가 컬렉션인 것 같습니다.이 경우 enum을 사용하는 것이 좋습니다.
import enum
class myClass(enum.Enum):
a = "12"
b = "34"
속성을 나열하시겠습니까?이보다 쉬운 것은 없습니다.
for attr in myClass:
print("Name / Value:", attr.name, attr.value)
두 가지 기능:
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'}
다음은 제가 원하는 것입니다.
테스트 데이터
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']
마법 속성이 아닌 속성과 값을 가져오는 빠른 함수입니다.
이 유틸리티 레시피의 사용은 코드나 설명서를 자세히 다루지 않고 클래스 또는 개체를 빠르게 소개하기 위한 것입니다.제가 그것을 사용했을 때, 저는 단지 그 수업이 가지고 있는 것들을 알고 싶었고, 무엇이 기능이고 무엇이 기능이 아닌지를 구분하고 싶었습니다. 분명히 저는 왜 제가 필요하다고 생각했는지 기억하지 못합니다.
예를 들어, 저는 Python Faker를 사용했지만 무엇이든 실제로 사용할 수 있습니다.
from faker import Faker
fake = Faker()
def get_class_props(cls):
for p in dir(cls):
if not p.startswith('__'):
attr_value = getattr(cls, p)
if p.startswith('_'):
print(f'- {p} (private): {attr_value}')
else:
print(f'- {p}: {attr_value}')
get_class_props(fake)
- _factories (private): [<faker.generator.Generator object at 0x00000138D01D28C8>]
# - _factory_map (private): OrderedDict([('en_US', <faker.generator.Generator object at 0x00000138D01D28C8>)])
# - _locales (private): ['en_US']
# - _map_provider_method (private): <bound method Faker._map_provider_method of <faker.proxy.Faker object at 0x00000138D017AD88>>
# - _select_factory (private): <bound method Faker._select_factory of <faker.proxy.Faker object at 0x00000138D017AD88>>
# - _unique_proxy (private): <faker.proxy.UniqueProxy object at 0x00000138D017A308>
# - _weights (private): None
# - aba: <bound method Provider.aba of <faker.providers.bank.en_GB.Provider object at 0x00000138D281DBC8>>
# - add_provider: <bound method Generator.add_provider of <faker.generator.Generator object at 0x00000138D01D28C8>>
# - address: <bound method Provider.address of <faker.providers.address.en_US.Provider object at 0x00000138D2810DC8>>
# ...
함수 정의를 정리하려면 호출 가능한 모든 '함수'를 정의하는 이 변형을 대신 사용합니다.
from faker import Faker
fake = Faker()
def get_class_props(cls):
for p in dir(cls):
if not p.startswith('__'):
attr_value = getattr(cls, p)
is_function = callable(attr_value)
if p.startswith('_'):
print(f'- {p} (private): {attr_value if not is_function else "funciton"}')
else:
print(f'- {p}: {attr_value if not is_function else "funciton"}')
- _factories (private): [<faker.generator.Generator object at 0x0000018A11D49C48>]
- _factory_map (private): OrderedDict([('en_US', <faker.generator.Generator object at 0x0000018A11D49C48>)])
- _locales (private): ['en_US']
- _map_provider_method (private): funciton
- _select_factory (private): funciton
- _unique_proxy (private): <faker.proxy.UniqueProxy object at 0x0000018A11D49748>
- _weights (private): None
- aba: funciton
get_class_props(fake)
위의 답변에 필터링 기능을 추가하려면:
import inspect
import re
def getClassMembers(obj, name=None, mbrcat='all'):
# name : filter by attribute name
# mbrcat : filter members by items category : all, methods or attributes
dic_cat= {
'all' : lambda a: a,
'meth' : lambda a: inspect.isroutine(a),
'attr' : lambda a: not(inspect.isroutine(a))
}
return [str(_name)+' : '+str(member)
for _name, member in inspect.getmembers(obj, dic_cat[mbrcat])
if ((name==None) or (name in _name)) and (not(re.search(r'(^\_\_|\_\_$)' ,_name))) ]
전화 번호 1:
getClassMembers(myClass.browse(264917),'state')
#Output:
['_compute_activity_state : <bound method xxx._compute_activity_state of classXXX >'
'extract_state : no_extract_requested',
'invoice_payment_state : paid',
'state : posted'
]
전화 번호 2:
getClassMembers(myClass.browse(264917),'state','meth')
#Output:
['_compute_activity_state : <bound method xxx._compute_activity_state of classXXX >'
]
3번 전화:
getClassMembers(myClass.browse(264917),'state','attr')
#Ouput:
[
'extract_state : no_extract_requested',
'invoice_payment_state : paid',
'state : posted'
]
이것이 3년 전의 일이라는 것을 알지만, 미래에 이 질문을 듣게 될 사람들을 위해, 저는:
class_name.attribute
잘 작동합니다.
사용할 수 있습니다.MyClass.__attrs__클래스의 모든 속성을 제공합니다.그 이상은 아닙니다.
언급URL : https://stackoverflow.com/questions/9058305/getting-attributes-of-a-class
'programing' 카테고리의 다른 글
| SQL에서 199.96 - 0 = 200인 이유는 무엇입니까? (0) | 2023.07.06 |
|---|---|
| 쿼리라는 JPA의 IN 절에서 동적 매개 변수를 사용하는 방법은 무엇입니까? (0) | 2023.07.06 |
| .NET의 디버그 대 릴리스 (0) | 2023.07.06 |
| JdbcTemplate "queryForObject" 및 "query"는 봄에 더 이상 사용되지 않습니다.무엇으로 대체해야 합니까? (0) | 2023.07.06 |
| SQL Server 2008 특수 스키마에서 모든 테이블 삭제 (0) | 2023.07.06 |