Использование переменных для имен классов в Python?
Я хочу знать, как использовать переменные для объектов и имен функций в Python. В PHP вы можете сделать это:
$className = "MyClass";
$newObject = new $className();
Как вы делаете такие вещи в Python? Или я совершенно не ценю фундаментальную разницу с Python, и если да, то что это?
6 ответов
В Python
className = MyClass
newObject = className()
Первая строка делает переменную className
относиться к тому же, что и MyClass
, Затем следующая строка вызывает MyClass
конструктор через className
переменная.
В качестве конкретного примера:
>>> className = list
>>> newObject = className()
>>> newObject
[]
(В Python list
является конструктором для list
учебный класс.)
Разница в том, что в PHP вы представляете имя класса, на который вы хотите сослаться, как строку, а в Python вы можете напрямую ссылаться на тот же класс. Если вы должны использовать строку (например, если имя класса создается динамически), то вам нужно будет использовать другие методы.
Предполагая, что у some_module есть класс с именем "class_name":
import some_module
klass = getattr(some_module, "class_name")
some_object = klass()
Я должен отметить, что вы должны быть осторожны: превращение строк в код может быть опасным, если строка получена от пользователя, поэтому в этой ситуации следует помнить о безопасности.:)
Еще один метод (при условии, что мы все еще используем "имя_класса"):
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 параметра: имя, базы, атрибуты
>>> 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()
как показано в ответе Колейфера, намного превосходит это решение.
Я предпочитаю использовать словарь для хранения сопоставления класса со строкой.
>>> class AB:
... def __init__(self, tt):
... print(tt, "from class AB")
...
>>> class BC:
... def __init__(self, tt):
... print(tt, "from class BC")
...
>>> x = { "ab": AB, "bc": BC}
>>> x
{'ab': <class '__main__.AB'>, 'bc': <class '__main__.BC'>}
>>>
>>> x['ab']('hello')
hello from class AB
<__main__.AB object at 0x10dd14b20>
>>> x['bc']('hello')
hello from class BC
<__main__.BC object at 0x10eb33dc0>