문제

문자열 인수를 취하고 해당 문자열에서 Python에서 이름이 지정된 클래스의 개체를 만들 필요가 있습니다. Java에서는 사용할 것입니다 Class.forName().newInstance(). 파이썬에 동등한 것이 있습니까?


응답에 감사드립니다. 내가하고있는 일을 알고 싶어하는 사람들에게 대답하기 위해 : 명령 줄 인수를 클래스 이름으로 사용하고 인스턴스화하고 싶습니다. 저는 실제로 Jython으로 프로그래밍하고 Java 클래스를 인스턴스화하므로 질문의 Java가 있습니다. getattr() 잘 작동합니다. 고맙습니다.

도움이 되었습니까?

해결책

Python의 반사는 Java보다 훨씬 쉽고 훨씬 더 유연합니다.

나는 이것을 읽는 것이 좋습니다 지도 시간

자격을 갖춘 클래스 이름을 가져 와서 클래스를 반환하는 직접 기능 (내가 알고있는)은 없지만,이를 만들 때 필요한 모든 조각이 있고 함께 연결할 수 있습니다.

그래도 한 가지 조언 : 파이썬에있을 때 Java 스타일로 프로그램을 시도하지 마십시오.

당신이하려고하는 것이 무엇인지 설명 할 수 있다면, 우리는 당신이 더 많은 파이낸스 방법을 찾는 데 도움을 줄 수 있습니다.

다음은 원하는 작업을 수행하는 기능입니다.

def get_class( kls ):
    parts = kls.split('.')
    module = ".".join(parts[:-1])
    m = __import__( module )
    for comp in parts[1:]:
        m = getattr(m, comp)            
    return m

이 기능의 반환 값을 클래스 자체 인 것처럼 사용할 수 있습니다.

사용 예는 다음과 같습니다.

>>> D = get_class("datetime.datetime")
>>> D
<type 'datetime.datetime'>
>>> D.now()
datetime.datetime(2009, 1, 17, 2, 15, 58, 883000)
>>> a = D( 2010, 4, 22 )
>>> a
datetime.datetime(2010, 4, 22, 0, 0)
>>> 

그게 어떻게 작동합니까?

우리는 사용하고 있습니다 __import__ 클래스를 보유하는 모듈을 가져 오려면 먼저 자격을 갖춘 이름에서 모듈 이름을 추출해야합니다. 그런 다음 모듈을 가져옵니다.

m = __import__( module )

이 경우 m 최상위 모듈 만 참조하면

예를 들어, 수업이 거주하는 경우 foo.baz 그러면 모듈 m 모듈이 될 것입니다 foo
우리는 쉽게 참조를 얻을 수 있습니다 foo.baz 사용 getattr( m, 'baz' )

최상위 모듈에서 클래스로 이동하려면 재귀 적으로 사용해야합니다. gettatr 클래스 이름의 부분에

예를 들어, 클래스 이름이 인 경우 말하십시오 foo.baz.bar.Model 그런 다음 우리는 이것을합니다 :

m = __import__( "foo.baz.bar" ) #m is package foo
m = getattr( m, "baz" ) #m is package baz
m = getattr( m, "bar" ) #m is module bar
m = getattr( m, "Model" ) #m is class Model

이것이이 루프에서 일어나는 일입니다.

for comp in parts[1:]:
    m = getattr(m, comp)    

루프 끝에 m 수업에 대한 참조가 될 것입니다. 이것은 그것을 의미합니다 m 실제로 클래스 ITSLEF입니다. 예를 들어 다음과 같이 할 수 있습니다.

a = m() #instantiate a new instance of the class    
b = m( arg1, arg2 ) # pass arguments to the constructor

다른 팁

클래스가 귀하의 범위에 있다고 가정합니다.

globals()['classname'](args, to, constructor)

그렇지 않으면:

getattr(someModule, 'classname')(args, to, constructor)

편집 : 참고, 당신은 getAttr에 'foo.bar'와 같은 이름을 줄 수 없습니다. 당신은 그것을 분할해야합니다. 각 조각에서 getAttr ()을 호출하십시오. 이것은 다음을 처리합니다.

module, rest = 'foo.bar.baz'.split('.', 1)
fooBar = reduce(lambda a, b: getattr(a, b), rest.split('.'), globals()[module])
someVar = fooBar(args, to, constructor)
def import_class_from_string(path):
    from importlib import import_module
    module_path, _, class_name = path.rpartition('.')
    mod = import_module(module_path)
    klass = getattr(mod, class_name)
    return klass

용법

In [59]: raise import_class_from_string('google.appengine.runtime.apiproxy_errors.DeadlineExceededError')()
---------------------------------------------------------------------------
DeadlineExceededError                     Traceback (most recent call last)
<ipython-input-59-b4e59d809b2f> in <module>()
----> 1 raise import_class_from_string('google.appengine.runtime.apiproxy_errors.DeadlineExceededError')()

DeadlineExceededError: 

또 다른 구현.

def import_class(class_string):
    """Returns class object specified by a string.

    Args:
        class_string: The string representing a class.

    Raises:
        ValueError if module part of the class is not specified.
    """
    module_name, _, class_name = class_string.rpartition('.')
    if module_name == '':
        raise ValueError('Class name must contain module part.')
    return getattr(
        __import__(module_name, globals(), locals(), [class_name], -1),
        class_name)

시작 대신 중간에서 이것에 접근하는 것 같습니다. 당신은 정말로 무엇을하려고합니까? 주어진 문자열과 관련된 클래스를 찾는 것은 끝의 수단입니다.

자신의 정신 리팩토링이 필요한 문제를 명확히하면 더 나은 해결책이 나타날 수 있습니다.

예를 들어 : 유형 이름과 매개 변수 세트에 따라 저장된 객체를로드하려고합니까? 파이썬은 이것을 피할 수없고 당신은 피클 모듈. 그리고 혼란스러운 프로세스가 당신이 설명하는 것을 정확하게 수행하더라도 내부적으로 어떻게 작동하는지 걱정할 필요가 없습니다.

>>> class A(object):
...   def __init__(self, v):
...     self.v = v
...   def __reduce__(self):
...     return (self.__class__, (self.v,))
>>> a = A("example")
>>> import pickle
>>> b = pickle.loads(pickle.dumps(a))
>>> a.v, b.v
('example', 'example')
>>> a is b
False

이것은 Python Standard Library에서 UnitTest.testloader.loadTestSfromName으로 찾을 수 있습니다. 불행히도이 방법은 추가 테스트 관련 활동을 수행하지만이 첫 번째 HA는 재사용 할 수 있습니다. 테스트 관련 기능을 제거하기 위해 편집했습니다.

def get_object(name):
    """Retrieve a python object, given its dotted.name."""
    parts = name.split('.')
    parts_copy = parts[:]
    while parts_copy:
        try:
            module = __import__('.'.join(parts_copy))
            break
        except ImportError:
            del parts_copy[-1]
            if not parts_copy: raise
    parts = parts[1:]

    obj = module
    for part in parts:
        parent, obj = obj, getattr(obj, part)

    return obj
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top