it-swarm.com.de

Entspricht python Java Class.forName ()?

Ich muss ein String-Argument nehmen und in Python ein Objekt der in diesem String genannten Klasse erstellen. In Java würde ich Class.forName().newInstance() verwenden. Gibt es ein Äquivalent in Python?


Danke für die Antworten. Um diejenigen zu beantworten, die wissen möchten, was ich tue: Ich möchte ein Befehlszeilenargument als Klassennamen verwenden und es instanziieren. Ich programmiere tatsächlich in Jython und instanziiere Java Klassen, daher die Java-Fähigkeit der Frage. getattr() funktioniert großartig. Vielen Dank.

87
Jason

Das Reflektieren in python ist viel einfacher und flexibler als in Java.

Ich empfehle das Lesen Tutorial

Es gibt keine direkte Funktion (die ich kenne), die einen vollständig qualifizierten Klassennamen annimmt und die Klasse zurückgibt. Sie haben jedoch alle Teile, die Sie zum Aufbau benötigen, und Sie können sie miteinander verbinden.

Ein kleiner Tipp: Versuchen Sie nicht, in Python im Java -Stil zu programmieren.

Wenn Sie erklären können, was Sie tun möchten, können wir Ihnen vielleicht dabei helfen, eine pythonischere Methode zu finden.

Hier ist eine Funktion, die das macht, was Sie wollen:

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

Sie können den Rückgabewert dieser Funktion so verwenden, als wäre es die Klasse selbst.

Hier ist ein Anwendungsbeispiel:

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

Wie funktioniert das?

Wir verwenden __import__, Um das Modul zu importieren, das die Klasse enthält. Dazu müssen wir zuerst den Modulnamen aus dem vollständig qualifizierten Namen extrahieren. Dann importieren wir das Modul:

m = __import__( module )

In diesem Fall bezieht sich m nur auf das Modul der obersten Ebene.

Wenn Ihre Klasse beispielsweise im Modul foo.baz Lebt, ist m das Modul foo.
Mit getattr( m, 'baz' ) können wir leicht einen Verweis auf foo.baz Erhalten.

Um vom Modul der obersten Ebene zur Klasse zu gelangen, müssen Sie gettatr für die Teile des Klassennamens rekursiv verwenden

Sagen Sie zum Beispiel, wenn Ihr Klassenname foo.baz.bar.Model Ist, dann machen wir das:

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

Dies ist, was in dieser Schleife passiert:

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

Am Ende der Schleife ist m ein Verweis auf die Klasse. Dies bedeutet, dass m tatsächlich die Klasse itslef ist, die Sie zum Beispiel ausführen können:

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

Angenommen, die Klasse liegt in Ihrem Bereich:

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

Andernfalls:

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

Edit: Beachte, dass du getattr keinen Namen wie 'foo.bar' geben kannst. Sie müssen es durch teilen. und rufe getattr () für jedes Teil von links nach rechts auf. Damit wird Folgendes erledigt:

module, rest = 'foo.bar.baz'.split('.', 1)
fooBar = reduce(lambda a, b: getattr(a, b), rest.split('.'), globals()[module])
someVar = fooBar(args, to, constructor)
25
Cody Brocious
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

Verwendung

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: 
11
Pat

Noch eine andere Implementierung.

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)
4
grayhemp

Anscheinend nähern Sie sich dem eher von der Mitte als von Anfang an. Was versuchst du wirklich zu tun? Das Finden der einer bestimmten Zeichenfolge zugeordneten Klasse ist ein Mittel zum Zweck.

Wenn Sie Ihr Problem klären, das möglicherweise Ihr eigenes mentales Refactoring erfordert, bietet sich möglicherweise eine bessere Lösung an.

Zum Beispiel: Versuchen Sie, ein gespeichertes Objekt basierend auf seinem Typnamen und einer Reihe von Parametern zu laden? Python buchstabiert dieses Abbeizen, und Sie sollten sich das Pickle-Modul ansehen. Auch wenn das Abbeizen genau das tut, was Sie beschreiben, müssen Sie sich keine Gedanken darüber machen, wie es funktioniert intern:

>>> 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
3
Roger Pate

Dies befindet sich in der Standardbibliothek python=================================================================================== bearbeitete es, um die testbezogene Funktionalität zu entfernen:

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
1
bukzor