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-массивах - но может вычислять строку как тип.

Другие вопросы по тегам