지정된 클래스의 모든 하위 클래스를 찾으려면 어떻게 해야 합니까?
Python의 기본 클래스에서 상속된 모든 클래스를 얻기 위한 실무적인 접근법이 필요합니다.
의 클래스 '아카운트', '아카운트', '아카운트'에서 )object
3)에서는로 Python 3)을 하고 있습니다.__subclasses__
'CHANGE: 'CHANGE: 'CHANGE:
class Foo(object): pass
class Bar(Foo): pass
class Baz(Foo): pass
class Bing(Bar): pass
서브클래스의 이름은 다음과 같습니다.
print([cls.__name__ for cls in Foo.__subclasses__()])
# ['Bar', 'Baz']
서브클래스는 다음과 같습니다.
print(Foo.__subclasses__())
# [<class '__main__.Bar'>, <class '__main__.Baz'>]
리스트 되어 있는 것을 합니다.Foo
★★★★★★★★★★★★★★★★★★:
for cls in Foo.__subclasses__():
print(cls.__base__)
# <class '__main__.Foo'>
# <class '__main__.Foo'>
서브 서브클래스를 원하시면 반복하셔야 합니다.
def all_subclasses(cls):
return set(cls.__subclasses__()).union(
[s for c in cls.__subclasses__() for s in all_subclasses(c)])
print(all_subclasses(Foo))
# {<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>}
아직 되지 않은 를 들어 서브클래스의않은 경우)는아직 하지 않으며 Import가 .__subclasses__
찾을 수 없을 거야
'이름 지어달라'고 하셨잖아요.Python 클래스는 퍼스트 클래스 오브젝트이기 때문에 클래스 대신 클래스 이름을 가진 문자열을 사용할 필요가 없습니다.당신은 그냥 직접 그 수업을 이용할 수 있고, 아마 그렇게 해야 할 것이다.
두 는 지정된 후 를 사용하여 . 지정된 이름을 가진 클래스를 찾은 다음 다음 다음 하위 클래스를 찾습니다.__subclasses__
위와 같이
이름에서 클래스를 찾는 방법은 원하는 위치에 따라 달라집니다.클래스를 찾으려는 코드와 동일한 모듈에서 찾을 수 있는 경우
cls = globals()[name]
그 일을 해내거나, 지역 주민에게서 찾을 수 있을 것 같지 않은 경우라면,
cls = locals()[name]
가 임의의될 수 경우 이름이 포함되어 를 들어, 「수식명」은 「수식명입니다.'pkg.module.Foo'
한 것이 'Foo'
을 사용하다importlib
아트리뷰트
import importlib
modname, _, clsname = name.rpartition('.')
mod = importlib.import_module(modname)
cls = getattr(mod, clsname)
, 클래스는 수 있습니다.cls.__subclasses__()
이치노
에는 " " " 를 참조하십시오..__subclasses__()
정상적으로 동작합니다.모든 서브클래스, 서브클래스 등을 원하는 경우 이를 위한 함수가 필요합니다.
다음은 특정 클래스의 모든 서브클래스를 재귀적으로 찾는 읽기 쉬운 간단한 함수입니다.
def get_all_subclasses(cls):
all_subclasses = []
for subclass in cls.__subclasses__():
all_subclasses.append(subclass)
all_subclasses.extend(get_all_subclasses(subclass))
return all_subclasses
일반적인 형태로 가장 간단한 솔루션:
def get_subclasses(cls):
for subclass in cls.__subclasses__():
yield from get_subclasses(subclass)
yield subclass
또한 다음에서 상속하는 단일 클래스가 있는 경우 클래스 메서드:
@classmethod
def get_subclasses(cls):
for subclass in cls.__subclasses__():
yield from subclass.get_subclasses()
yield subclass
Python 3.6 -__init_subclass__
되었듯이 ''를 확인하실 수 .__subclasses__
python 3.6은 메서드를 재정의하여 이 속성 생성을 수정할 수 있으므로 하위 클래스 목록을 가져옵니다.
class PluginBase:
subclasses = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.subclasses.append(cls)
class Plugin1(PluginBase):
pass
class Plugin2(PluginBase):
pass
무엇을, '아까', '아까', '아까', '아까' 등의 수 .__subclasses__
및 이 목록에서 서브클래스를 생략/추가합니다.
은 (@아닌)되어 더 : @unutbu (@unutbu ) 。vars()['Foo']
그래서 제 글의 주요 요점은 더 이상 적용되지 않습니다.
FWIW, 로컬로 정의된 클래스로만 작업하는 @unutbu의 답변은 다음과 같습니다.eval()
vars()
현재 범위에 정의되어 있는 클래스뿐만 아니라 액세스 가능한 클래스에서도 동작합니다.
eval()
수 있는 도 제시되어 있습니다
이 예는 사용상의 있습니다.vars()
:
class Foo(object): pass
class Bar(Foo): pass
class Baz(Foo): pass
class Bing(Bar): pass
# unutbu's approach
def all_subclasses(cls):
return cls.__subclasses__() + [g for s in cls.__subclasses__()
for g in all_subclasses(s)]
print(all_subclasses(vars()['Foo'])) # Fine because Foo is in scope
# -> [<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>]
def func(): # won't work because Foo class is not locally defined
print(all_subclasses(vars()['Foo']))
try:
func() # not OK because Foo is not local to func()
except Exception as e:
print('calling func() raised exception: {!r}'.format(e))
# -> calling func() raised exception: KeyError('Foo',)
print(all_subclasses(eval('Foo'))) # OK
# -> [<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>]
# using eval('xxx') instead of vars()['xxx']
def func2():
print(all_subclasses(eval('Foo')))
func2() # Works
# -> [<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>]
은, RPV, RPV 를 하는 것으로 할 수 .eval('ClassName')
함수로 , 「」, 「」, 「」, 「」, 「」를 해 수 있는 , 사용이 용이하게 할 수 .eval()
그것 which which which which와는 vars()
구애받지 않습니다.문맥에 구애받지 않습니다.
# easier to use version
def all_subclasses2(classname):
direct_subclasses = eval(classname).__subclasses__()
return direct_subclasses + [g for s in direct_subclasses
for g in all_subclasses2(s.__name__)]
# pass 'xxx' instead of eval('xxx')
def func_ez():
print(all_subclasses2('Foo')) # simpler
func_ez()
# -> [<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>]
마지막으로, 이 기능을 사용하지 않도록 하는 것이 가능하고 경우에 따라서는 중요할 수도 있습니다.eval()
보안상의 이유로, 이하에 없는 버전을 나타냅니다.
def get_all_subclasses(cls):
""" Generator of all a class's subclasses. """
try:
for subclass in cls.__subclasses__():
yield subclass
for subclass in get_all_subclasses(subclass):
yield subclass
except TypeError:
return
def all_subclasses3(classname):
for cls in get_all_subclasses(object): # object is base of all new-style classes.
if cls.__name__.split('.')[-1] == classname:
break
else:
raise ValueError('class %s not found' % classname)
direct_subclasses = cls.__subclasses__()
return direct_subclasses + [g for s in direct_subclasses
for g in all_subclasses3(s.__name__)]
# no eval('xxx')
def func3():
print(all_subclasses3('Foo'))
func3() # Also works
# -> [<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>]
다음은 심플하지만 효율적인 코드 버전입니다.
def get_all_subclasses(cls):
subclass_list = []
def recurse(klass):
for subclass in klass.__subclasses__():
subclass_list.append(subclass)
recurse(subclass)
recurse(cls)
return set(subclass_list)
의 복잡성은 그그 its its its its its its its its its its이다.O(n)
서 ''는n
다중 상속이 없는 경우 모든 하위 클래스의 수입니다.는 (1)이 될 수 O(nlogn)
또는 (2)일 경우 (2)O(n^2)
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
모든 서브클래스의 목록을 가져오는 훨씬 짧은 버전:
from itertools import chain
def subclasses(cls):
return list(
chain.from_iterable(
[list(chain.from_iterable([[x], subclasses(x)])) for x in cls.__subclasses__()]
)
)
다음은 재귀가 없는 버전입니다.
def get_subclasses_gen(cls):
def _subclasses(classes, seen):
while True:
subclasses = sum((x.__subclasses__() for x in classes), [])
yield from classes
yield from seen
found = []
if not subclasses:
return
classes = subclasses
seen = found
return _subclasses([cls], [])
이는 원래 클래스를 반환한다는 점에서 다른 구현과 다릅니다.이는 코드를 심플하게 하고 다음 사항을 수행하기 때문입니다.
class Ham(object):
pass
assert(issubclass(Ham, Ham)) # True
get_subclasses_gen이 약간 이상해 보이는 경우, 이는 테일 재귀 구현을 루프 생성기로 변환하여 작성되었기 때문입니다.
def get_subclasses(cls):
def _subclasses(classes, seen):
subclasses = sum(*(frozenset(x.__subclasses__()) for x in classes))
found = classes + seen
if not subclasses:
return found
return _subclasses(subclasses, found)
return _subclasses([cls], [])
지정된 클래스의 모든 서브클래스를 찾으려면 어떻게 해야 합니까?
물론 객체 자체에 접근할 수 있다면 쉽게 할 수 있습니다.
단순히 이름을 붙이는 것은 좋지 않습니다.같은 이름의 클래스가 여러 개 있을 수 있고, 같은 모듈에 정의되어 있을 수도 있기 때문입니다.
또 다른 답변을 위한 구현을 작성했습니다.그것은 이 질문에 대한 답변으로, 여기 있는 다른 솔루션보다 조금 더 우아합니다.다음은 예를 제시하겠습니다.
def get_subclasses(cls):
"""returns all subclasses of argument, cls"""
if issubclass(cls, type):
subclasses = cls.__subclasses__(cls)
else:
subclasses = cls.__subclasses__()
for subclass in subclasses:
subclasses.extend(get_subclasses(subclass))
return subclasses
사용방법:
>>> import pprint
>>> list_of_classes = get_subclasses(int)
>>> pprint.pprint(list_of_classes)
[<class 'bool'>,
<enum 'IntEnum'>,
<enum 'IntFlag'>,
<class 'sre_constants._NamedIntConstant'>,
<class 'subprocess.Handle'>,
<enum '_ParameterKind'>,
<enum 'Signals'>,
<enum 'Handlers'>,
<enum 'RegexFlag'>]
은 특별한 __subclasses__()
@unutbu가 말하는 수업 방식, 그래서 나는 그것을 단지 연습으로 제시한다.subclasses()
function defined는 모든 서브클래스 이름을 서브클래스 자체에 매핑하는 사전을 반환합니다.
def traced_subclass(baseclass):
class _SubclassTracer(type):
def __new__(cls, classname, bases, classdict):
obj = type(classname, bases, classdict)
if baseclass in bases: # sanity check
attrname = '_%s__derived' % baseclass.__name__
derived = getattr(baseclass, attrname, {})
derived.update( {classname:obj} )
setattr(baseclass, attrname, derived)
return obj
return _SubclassTracer
def subclasses(baseclass):
attrname = '_%s__derived' % baseclass.__name__
return getattr(baseclass, attrname, None)
class BaseClass(object):
pass
class SubclassA(BaseClass):
__metaclass__ = traced_subclass(BaseClass)
class SubclassB(BaseClass):
__metaclass__ = traced_subclass(BaseClass)
print subclasses(BaseClass)
출력:
{'SubclassB': <class '__main__.SubclassB'>,
'SubclassA': <class '__main__.SubclassA'>}
언급URL : https://stackoverflow.com/questions/3862310/how-to-find-all-the-subclasses-of-a-class-given-its-name
'source' 카테고리의 다른 글
다국어 정규 표현 단위 테스트는 어디서 볼 수 있나요? (0) | 2022.09.06 |
---|---|
포인터로 가리키는 int의 증분값 (0) | 2022.09.06 |
매개 변수의 실제 유형을 기반으로 한 메서드 선택 오버로드 (0) | 2022.09.06 |
지정된 키가 사전에 이미 있는지 확인합니다. (0) | 2022.09.06 |
Vue | 특정 NPM 패키지에서 스타일시트를 Import하는 방법 (0) | 2022.09.06 |