python: динамическое приведение типов - преобразование объекта Unicode в объект Python
Это проблема, с которой я сталкиваюсь для проекта конвейера данных. У меня есть 2 источника данных. Один содержит все пользовательские данные, другой содержит метаданные о том, что все столбцы мы должны обработать от пользовательских данных до вывода.
Так что Python хорош с динамическим приведением типов, как если бы я сказал
a = float
b = "25.123"
c = a(b)
print(c)
>> 25.123
Это то, что я хочу сделать, я хочу динамически печатать приведенные значения, чтобы правильно их обрабатывать. Тип извлекается из источника данных метаданных. Проблема заключается в том, что когда я делаю запрос модели django к метаданным, я получаю объекты Unicode.
a = model.objects.filter(id = 'id') # get the type variable from the meta-data
a = a[0]['type']
print(a)
>> u'float'
a("123.123")
>> TypeError: 'unicode' object is not callable
Как мне преобразовать этот u'float 'в float? Есть ли у этого подхода лучшие альтернативы? Я проверил это, но это не работает
Открыто для всех предложений
3 ответа
В вашем первом примере, где a = float
, a
это встроенная функция, но во втором примере a = u"float"
, a
является строкой Unicode. Если вы хотите преобразовать полную "динамичность" встроенного типа без необходимости создания отображения, вы можете сделать это:
# for Python 2
a = u"float"
b = "123.123"
import __builtin__
print getattr(__builtin__, a.decode())(b)
# 123.123
# for Python 3+
a = u"float"
b = "123.123"
import builtins
print(getattr(builtins, a)(b))
# 123.123
Я бы посоветовал вам не использовать eval()
(как предполагает другой ответ), потому что это может привести к серьезным рискам безопасности. Вот почему я использовал __builtin__
/ builtins
модуль и getattr()
чтобы получить float(...)
функция.
Вы также можете создать отображение (т.е. dict
), чтобы отобразить строку Юникода в соответствующую функцию (предложено этим комментарием):
# both Python 2 and 3
a = u"float"
b = "123.123"
mapping = {u"float": float, u"int": int, u"str": str, u"list": list}
print(mapping[a](b))
# 123.123
Использование сопоставления является наиболее безопасным способом, но оно ограничивает вашу "динамичность" только типами, перечисленными в сопоставлении.
Вы можете использовать eval()
функция для оценки кода, но вы должны быть осторожны с этой функцией! В противном случае, вы могли бы взглянуть на этот пост. Другое решение состоит в том, чтобы заранее определить разрешенные типы и собрать их в отображении словаря. typeName
с typeConstructor
,
Вы могли бы использовать astype
из обалденной библиотеки:
import numpy as np
np.array(('213.123')).astype(a)
по общему признанию, это должно пройти через массив, потому что astype()
работает на numpy-массивах - но может вычислять строку как тип.