Использование переменных для имен классов в Python?


Я хочу знать, как использовать переменные для имен объектов и функций в Python. В PHP вы можете сделать следующее:

$className = "MyClass";

$newObject = new $className();

Как вы делаете такие вещи в Python? Или, может быть, я совершенно не понимаю некоторого фундаментального различия с Python, и если да, то в чем оно заключается?

4 31

4 ответа:

В Python,

className = MyClass
newObject = className()

Первая строка заставляет переменную className ссылаться на то же самое, что и MyClass. Затем следующая строка вызывает конструктор MyClass через переменную className.

В качестве конкретного примера:

>>> className = list
>>> newObject = className()
>>> newObject
[]

(в Python, list является конструктором для класса list.)

Разница в том, что в PHP вы представляете имя класса, на который хотите ссылаться, как строку, в то время как в Python вы можете ссылаться на тот же самый класс напрямую. Если вы должны использовать string (например, если имя класса создается динамически), то вам нужно будет использовать другие методы.

Предполагая, что some_module имеет класс с именем "class_name":

import some_module
klass = getattr(some_module, "class_name")
some_object = klass()

Я должен отметить, что вы должны быть осторожны здесь: превращение строк в код может быть опасным, если строка пришла от пользователя, поэтому вы должны иметь в виду безопасность в этой ситуации. :)

Еще один метод (предполагая, что мы все еще используем "class_name"):

class_lookup = { 'class_name' : class_name }
some_object = class_lookup['class_name']()  #call the object once we've pulled it out of the dict
Последний метод, вероятно, является наиболее безопасным способом сделать это, так что это, вероятно, то, что вы должны использовать, если это вообще возможно.

Если вам нужно создать динамический класс в Python (то есть тот, чье имя является переменной), вы можете использовать type (), который принимает 3 парама: имя, основания, attrs

>>> class_name = 'MyClass'
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'})

<class '__main__.MyClass'>

>>> inst = klass()
>>> inst.msg
foobarbaz
    Заметьте, однако, что это не "инстанцирует" объект (т. е. не вызывает конструкторы и т. д. Он создает новый(!) класс с тем же именем.

Если у вас есть это:

class MyClass:
    def __init__(self):
        print "MyClass"

Затем вы обычно делаете следующее:

>>> x = MyClass()
MyClass

Но вы могли бы также сделать это, о чем, я думаю, вы просите:

>>> a = "MyClass"
>>> y = eval(a)()
MyClass
Но будьте очень осторожны с тем, где вы получаете строку, в которой вы используете "eval ()" - если она исходит от пользователя, вы, по сути, создаете огромную дыру в безопасности.

Обновление: использование type(), как показано в ответе колейфера, намного превосходит это решение.