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? Есть ли у этого подхода лучшие альтернативы? Я проверил это, но он не работает

Открыт для всех предложений


person skybunk    schedule 03.05.2018    source источник
comment
Я бы создал явное отображение строк в типы.   -  person juanpa.arrivillaga    schedule 03.05.2018


Ответы (3)


В вашем первом примере, где a = float, a - встроенная функция, но во втором примере a = u"float", a - это строка в Юникоде. Если вам нужна полная «динамичность» встроенного типа для преобразования без необходимости создания сопоставления, вы можете сделать это:

# 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__ / _ 8_ модуль и getattr() для получения функции float(...).


Вы также можете создать сопоставление (например, a dict), чтобы сопоставить строку Unicode с соответствующей функцией (предложенной этим комментарий):

# 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

Использование сопоставления - самый безопасный путь, но он ограничивает вашу «динамичность» только типами, перечисленными в сопоставлении.

person abccd    schedule 03.05.2018
comment
как это сделать с объектами date или datetime? предположим, что a = udate, getattr там не будет работать - person skybunk; 10.05.2018
comment
понял, поэтому вместо использования встроенного вы используете datetime - person skybunk; 10.05.2018

Вы можете использовать функцию eval() для оценки кода, но с этой функцией нужно быть осторожным! В противном случае вы можете взглянуть на это сообщение. Другое решение - предварительно определить разрешенные типы и собрать их в словарном сопоставлении typeName с помощью typeConstructor.

person Picnix_    schedule 03.05.2018
comment
лучше иметь заранее определенный dict, eval () может привести к проблемам в будущем - person skybunk; 03.05.2018
comment
Да, поэтому я подчеркиваю, что нужно быть осторожным. Может появиться много недостатков безопасности, поэтому я не буду рекомендовать eval(), но это было первое, что пришло мне в голову. - person Picnix_; 03.05.2018

Вы можете использовать astype из библиотеки numpy:

import numpy as np
np.array(('213.123')).astype(a)

по общему признанию, это должно проходить через массив, потому что astype() работает с numpy-массивами, но он может вычислять строку как тип.

person SpghttCd    schedule 03.05.2018