Вопрос или проблема
Я пишу пакет на python, который выполняет множество операций с массивами с использованием разных библиотек (numpy, numexp, pyfftw). Он состоит из нескольких утилитных скриптов и скрипта симуляции, который анализирует файл .ini и выполняет определенную симуляцию. Я хотел бы выбрать точность (в файле .ini), которая будет применяться ко всем вычислениям для данной симуляции.
Я хотел бы узнать, возможно ли реализовать это по следующей логике (код не работает):
#config.py
DTYPE = 'float64'
#utility.py
import numpy as np
from config import DTYPE
def create_array():
print(DTYPE)
arr = np.ones(10, dtype=DTYPE)
return arr
#simulation.py
from config import DTYPE
from utility import create_array
if __name__ == '__main__':
print(DTYPE)
precision = get_precision(ini_file)
DTYPE = precision
create_array()
Если точность ‘float32’, я хотел бы увидеть следующий вывод:
'float64'
'float32'
Я видел [эту проблему](https://github.com/numpy/numpy/issues/6860). Это неплохое решение, но поскольку я использую несколько библиотек, monkey-patching (np.array -> np.array(..., dtype=DTYPE)
) кажется не идеальным, и я хочу изменить точность от симуляции к симуляции.
Я понимаю, что мой код не работает, так как константа DTYPE
загружается во время импорта и изменяется во время выполнения.
Ответ или решение
Вопрос, который вы поднимаете, связан с динамической изменяемостью типа данных (точности плавающей запятой) в вашем Python-пакете. Действительно, при использовании констант (например, DTYPE
в вашем коде) важно понимать, что значения таких констант загружаются во время импорта, что делает их статичными в контексте модуля. Однако, есть несколько подходов, которые могут помочь вам реализовать требуемую функциональность.
Выбор подхода
-
Использование глобальных переменных: Один из простейших способов – это объявить переменную в основном скрипте, а затем передавать её значение при вызовах функций, которые требуют указанного типа данных. Это может быть реализовано следующим образом:
# config.py DTYPE = 'float64' # utility.py import numpy as np def create_array(dtype): print(dtype) arr = np.ones(10, dtype=dtype) return arr # simulation.py from config import DTYPE from utility import create_array def get_precision(ini_file): # Здесь должен быть код, который считывает .ini файл и возвращает нужную точность return 'float32' if __name__ == '__main__': print(DTYPE) # вывод из config.py precision = get_precision('path/to/ini_file') create_array(precision)
В этом варианте вы передаете
precision
непосредственно в функциюcreate_array
, что позволяет динамически изменять его на основе вашего .ini файла. -
Использование классов: Если ваш пакет становится более сложным, вы можете рассмотреть возможность создания класса, который будет хранить состояние (включая тип данных) и методы для выполнения операций:
# config.py class Config: def __init__(self, dtype='float64'): self.dtype = dtype # utility.py import numpy as np class ArrayUtility: def __init__(self, config): self.config = config def create_array(self): print(self.config.dtype) arr = np.ones(10, dtype=self.config.dtype) return arr # simulation.py from config import Config from utility import ArrayUtility def get_precision(ini_file): # Код для получения точности из файла .ini return 'float32' if __name__ == '__main__': config = Config() print(config.dtype) # вывод из Config precision = get_precision('path/to/ini_file') config.dtype = precision # обновление точности util = ArrayUtility(config) util.create_array()
Этот подход позволяет вам не только изменять тип данных, но и расширять функционал вашего пакета в будущем.
-
Использование контекста: Вы также можете рассмотреть использование контекстных менеджеров для изменения типа данных в определенной области кода.
Заключение
Каждый из упомянутых подходов имеет свои преимущества и недостатки, и выбор будет зависеть от требований к вашему проекту и его сложности. Применение динамического подхода к типам данных поможет вам настроить ваш пакет для гибкой работы с различными библиотеками, такими как NumPy, Numba и другие. Оптимизация вашего кода приведет к лучшему управлению памятью и улучшению производительности расчетов.
Не забудьте протестировать выбранный вариант, чтобы убедиться, что он соответствует вашим требованиям, и обеспечьте внимание к деталям при обработке различных сценариев.