Единицы измерения физических величин в программах на языке Python

Введение

Язык Python (правильно это читается "Пайтон", но в русскоязычном сообществе так же прижилось и прочтение "Питон", мне оно тоже больше по душе ;) в последнее время получил очень большую популярность в среде непрограммистов по двум причинам:

  • лёгкий синтаксис, очень близкий к естественным языкам и математическому мышлению;

  • огромное количество различных библиотек (модулей), написанных как на самом питоне, так и на более быстрых "профессиональных" языках С/С++ и Фортран.

Хотя для изучения основ Питона есть очень много хорошей литературы, в том числе и на русском языке, вопросы использования многих модулей описаны недостаточно. Особенно тяжело здесь русскоязычным инженерам. Этой статьёй я хочу начать цикл туториалов, в которых я поделюсь своим опытом использования языка Питон в практической инженерной деятельности. В настоящем туториале речь пойдёт о модуле Pint, который сильно упрощает манипулирование физическими величинами.

Настоящие туториалы нельзя рассматривать как основы языка Питон. Предполагается, что читатель с ними знаком, а так же знаком с модулями Math, CMath, Numpy, Scipy, Pandas. Язык Питон и перечисленные модули хорошо описаны в литературе и Интернете.

Для начала немного теории, что бы освежить мозг

В инженерных расчётах очень большое значение имеет приведение, преобразование и отображение единиц измерения. Результат любых инженерных измерений и расчётов не имеет никакого смысла, если не указаны две его основные характеристики: единица измерения и точность. О точности я напишу следующий туториал, а сейчас поговорим об единицах измерения.

Напомню основные определения:

Физической величиной называется физическое свойство материального объекта, процесса, физического явления, охарактеризованное количественно.

Значение физической величины выражается одним или несколькими числами, характеризующими эту физическую величину, с указанием единицы измерения.

Размером физической величины являются значения чисел, фигурирующих в значении физической величины.

Единицей измерения физической величины является величина фиксированного размера, которой присвоено числовое значение, равное единице. Применяется для количественного выражения однородных с ней физических величин.

Размерность физической величины — выражение, показывающее связь этой величины с основными величинами данной системы физических величин; записывается в виде произведения степеней сомножителей, соответствующих основным величинам, в котором численные коэффициенты опущены.

Системой единиц физических величин называют совокупность основных и производных единиц, основанную на некоторой системе величин. Широкое распространение получило всего лишь некоторое количество систем единиц. В большинстве случаев во многих странах пользуются метрической системой.

Измерить физическую величину – значит сравнить ее с другой такой же физической величиной, принятой за единицу. Например, длину предмета сравнивают с единицей длины, массу тела – с единицей веса и т.д. Но если один исследователь измерит длину в саженях, а другой в футах, им будет трудно сравнить эти две величины. Поэтому все физические величины во всем мире принято измерять в одних и тех же единицах. В 1963 году была принята Международная система единиц СИ (System international - SI). Для каждой физической величины в системе единиц должна быть предусмотрена соответствующая единица измерения. Эталоном единицы измерения является ее физическая реализация. Эталоном длины является метр – расстояние между двумя штрихами, нанесенными на стержне особой формы, изготовленном из сплава платины и иридия. Эталоном времени служит продолжительность какого-либо правильно повторяющегося процесса, в качестве которого выбрано движение Земли вокруг Солнца: один оборот Земля совершает за год. Но за единицу времени принимают не год, а секунду. Единицы измерения, для которых существуют физические эталоны, называют основными единицами

Производными единицами измерения физических величин называют такие единицы, для которых нет физических эталонов и которые определяются через соотношения основных единиц. Например, за единицу скорости принимают скорость такого равномерного прямолинейного движения, при котором тело за 1 с совершает перемещение в 1 м - поэтому единица скорости обозначается m/s. Единицей площади является площадь квадрата, длина каждой стороны которого равна 1 м - поэтому единица площади называется "квадратный метр" и обозначается m^2.

Приставки используются для того, что бы сделать запись значения физической величины более компактным. Например, 1000000\Omega = 1M\Omega. приставки бывают десятичные и двоичные. Десятичные приставки представляют собой множители 10^x\; | x \in \mathbb{N} -24 \leq x \leq 24. Двоичные приставки представляют собой множители 2^y\; | y \in \{ 10, 20, 30, 40, 50, 60, 70, 80\}.

Основные единицы системы СИ

Величина

Наименование

Обозначение

Длина

метр

m

Масса

килограмм

kg

Время

секунда

s

Сила электрического тока

ампер

A

Термодинамическая температура

кельвин

K

Сила света

канделла

cd

Количество веществ

моль

mol

Плоский угол

радиан

rad

Телесный угол

стерадиан

sr

Производные единицы системы СИ

Величина

Наименование

Обозначение

Выражение через основные единицы

Выражение через производные единицы

Частота

герц

Hz

1\s

-

Сила

ньютон

N

kg \cdot m / s^2

-

Давление

паскаль

Pa

kg / m \cdot s^2

N / m^2

Энергия, работа, количество теплоты

джоуль

J

kg \cdot m^2 /s^2

N \cdot m

Мощность, поток энергии

ватт

W

kg \cdot m^2/s^3

J / s

Количество электричества, заряд

кулон

С

A \cdot s

-

Электрическое напряжение, потенциал

вольт

V

kg \cdot m^2 / A \cdot s^3

W / A

Электрическая ёмкость

фарада

F

A^2 \cdot s^3 / kg \cdot m^2

C / V

Электрическое сопротивление

ом

Ω

{kg \cdot m^2} / {A^2 \cdot s^3}

{V} / {A}

Электропроводность

сименс

S

{A^2 \cdot s^3} / {kg \cdot m^2}

{A} / {V} или{1} / {Ω}

Поток магнитной индукции

вебер

Wb

{kg \cdot m^2} / {A \cdot s^2}

V \cdot s

Магнитная индукция

тесла

Т

{kg} . {A \cdot s^2}

{Wb} / {m^2}

Индуктивность

генри

H

{kg \cdot m^2} / {A^2 \cdot s^2}

{Wb} / {A}

Световой поток

люмен

Im

cd \cdot sr

-

Освещённость

люкс

Ix

m^2 \cdot cd \cdot sr

-

Физические и технические константы

Для удобства и наглядности работы, в том числе для перевода несистемных единиц в системные, кроме приставок и обозначения физических единиц, в модуле Pint определены некоторые физические константы:

Наименование

Значение

Обозначение

\pi

3.1415926535

pi

Экспонента

2.718281884

e

Скорость света

299792458 \; {m} / {s}

c speed_of_light

Гравитационная постоянная

9.806650 \; {m} / {s^2}

g_0 graviti

Вакуумная проницаемость

4 \cdot \pi \cdot 1e^{-7}\; {N}/{A^2}

mu_0 magnetic_constant

Диэлектрическая проницаемость

{1} / {\mu_0 \cdot c^2}

electric_constant

Вакуумный импеданс

\mu_0 \cdot c

Z_0 impedance_of_free_space characteristic_impedance_of_vacuum

Постоянная Планка

6.62606957e^{-34} J\cdot s

h

Постоянная Дирака

{h} / {2\pi}

hbar

Гравитационная константа Ньютона

6.67384 \cdot 10^{-11} \; {m^3} / {kg^{-1} \cdot s^{-2}}

newtonian_constant_of_gravitation

Молярная газовая постоянная

8.3144621 \; {J} / {mol^{-1} \cdot K^{-1}}

R

Число Авогадро

6.02214129 \cdot 10^{23} mol^{-1}

N_A

Постоянная Больцмана

1.3806488 \cdot 10^{-23} \; {J} / {K^{-1}}

k

Постоянная Вина

5.8789254 \cdot 10^{10} \; {Hz} / {K^{-1}}

wien_frequency_displacement_law_constant

Постоянная Ридберга

10973731.568539 \; m^{-1}

rydberg_constant

Масса электрона

9.10938291\cdot 10^{-31} kg

m_e electron_mass

Масса нейтрона

1.674927351 \cdot 10^{-27} kg

m_n neutron_mass

Масса протона

1.672621777 \cdot 10^{-27} kg

m_p proton_mass

Несистемные единицы

Модуль Pint содержит единицы не только системы СИ, но и других известных систем единиц, что позволяет применять его для перевода значений физических величин из одной системы единиц в другую. В модуле определено очень много разных единиц, поэтому не будем раздувать туториал ещё одной таблицей, вместо этого ниже будет показано, как получить названия нужных единиц средствами самого питона.

Десятичные приставки

Множитель

Название

Обозначение

10^{-24}

иокто

y

10^{-21}

зепто

z

10^{-18}

aттo

a

10^{-15}

фемто

f

10^{-12}

пико

p

10^{-9}

нано

n

10^{-6}

микро

μ

10^{-3}

милли

m

10^{-2}

санти

c

10^{-1}

деци

d

10^1

дека

deka

10^2

гекта

h

$10^3

кило

k

10^6

мега

M

10^9

гига

G

$10^{12}

тера

T

$10^{15}

пента

P

$10^{18}

экса

E

$10^{21}

зетта

Z

$10^{24}

иотта

Y

Двоичные приставки

Множитель

Название

Обозначение

2^{10}

киби

Ki

2^{20}

меби

Mi

2^{30}

гиби

Gi

2^{40}

теби

Ti

2^{50}

пеби

Pi

2^{60}

эксби

Ei

2^{70}

зеби

Zi

2^{80}

иоби

Yi

Дополнительные приставки

Кроме стандартных приставок системы СИ, в модуле Pint определены три дополнительные приставки:

Множитель

Обозначение

0.1

demi

0.5

semi

1.5

sesqui

Установка и начало использования модуля Pint

Установка модуля производится стандартным для Python образом:

c:\>pip install pint

Если вы используете менеджер Anaconda, то команда установки будет такой:

c:\>conda install pint --channels conda-forge

Для использования модуля его надо импортировать в вашу программу. Рекомендуется это делать следующими командами:

>>>from pint import UnitRegistry
>>>ureg = UnitRegistry()

Вторая строка инициализирует объект класса UnitRegistry, который хранит определения единиц измерения, их связи и обрабатывает преобразования между единицами (разумеется, имя объекта может быть произвольным, совсем не обязательно ureg; можно даже определить несколько таких объектов, хотя я не могу представить, для чего это может быть нужно). При этом объект ureg заполняется списком единиц и префиксов по умолчанию, полный список которых можно посмотреть в файле default_en.txt, который находится в папке, в которую установлена библиотека. Узнать расположение этой паки можно командой:

c:\>pip show pint

Name: Pint
Version: 0.19.2
Summary: Physical quantities module
Home-page: https://github.com/hgrecco/pint
Author: Hernan E. Grecco
Author-email: hernan.grecco@gmail.com
License: BSD
Location: c:\users\andre\anaconda3\lib\site-packages
Requires:
Required-by:

Другой способ увидеть, какие несистемные единицы уже определены в модуле. Для этого надо вызвать метод get_compatible_units() объекта класса UnitRegistry, передав ему величину интересующих единиц (в даном примере мы получаем возможные единицы измерения энергии):

>>>ureg.get_compatible_units('[energy]')
frozenset({<Unit('electron_volt')>,
           <Unit('rydberg')>,
           <Unit('hartree')>,
           <Unit('erg')>,
           <Unit('joule')>,
           <Unit('foot_pound')>,
           <Unit('calorie')>,
           <Unit('fifteen_degree_calorie')>,
           <Unit('international_calorie')>,
           <Unit('atmosphere_liter')>,
           <Unit('thermochemical_british_thermal_unit')>,
           <Unit('international_british_thermal_unit')>,
           <Unit('british_thermal_unit')>,
           <Unit('watt_hour')>,
           <Unit('US_therm')>,
           <Unit('therm')>,
           <Unit('ton_TNT')>,
           <Unit('tonne_of_oil_equivalent')>,
           <Unit('quadrillion_Btu')>})

Проверка того, определена ли единица измерения

Для того, что бы проверить, определена ли необходимая единица измерения, можно воспользоваться следующими командами Питона:

>>> 'MHz' in ureg
True
>>> 'gigatrees' in ureg
False

Дополнение списка единиц

Если требуемой единицы измерения в файле default_en.txt нет, её можно добавить тремя способами:
1. Дописать определение единицы в конец файла default_en.txt.
2. Создать свой собственный файл определения единиц, например, mydef.txt.
3. Добавить описание единицы программно.

Формат файла описания

Независимо от того, дописывается ли единица в файл default_en.txt или создаётся новый файл описания единиц, структура описания каждой единицы следующая:

hour = 60 * minute = h = hr
minute = 60 * second = min

Это довольно просто, не так ли? Мы говорим, что минута равна 60 секундам и также известна как "мин".

  1. Первое слово – это всегда каноническое имя.

  2. После знака равенства следует определение единицы, основанное на других, ранее определённых единицах.

  3. После следующего знака равенства, опционально, указывается символ единицы измерения.

  4. Наконец, опять же опционально, приводится список псевдонимов единицы измерения, разделенных знаками равенства. Если надо указать только псевдонимы без символа единицы, символ единицы должен быть заменён на символ "_":

millennium = 1e3 * year = _ = millennia

Эта команда определяет единицу "millennium", равную 1000 годам ("year", определена в файле default_en.txt) без символа единицы измерения. Так же определён псевдоним "millennia", который может использоваться в программе вместо обозначения "millennium".

Порядок определения единиц измерения не имеет значения, Pint разрешит зависимости, чтобы определить их в правильном порядке. Важно только, что бы все единицы, использованные справа от первого знака равенства, были определены в доступных файлах определения единиц. Если надо добавить единицу, которую нельзя выразить через другие определённые единицы, её следует выражать через эталонные физические размерности:

second = [time] = s = sec

  • time - это физическая величина

  • second - единица измерения времени (секунда)

Новые физические величины так же можно определять через другие физические величины:

[density] = [mass] / [volume]

Обратите внимание, что первичные физические величины не нужно объявлять.

Кроме основных единиц измерения, в файле описания определяются их кратные десятичные префиксы, они обозначаются конечным тире:

yocto- = 10.0**-24 = y-

Наконец, можно добавить псевдонимы к уже существующему определению единицы:

@alias meter = metro = metr

Кроме того, файл описания может содержать необрабатываемый библиотекой Pint комментарии, начинающиеся с символа "#" (как в синтаксисе Питона)

Создание собственного файла описания

Если вы добавляете новые описания в файл default_en.txt, то они могут пропасть при обновлении версии библиотеки - при этом будет установлен новый стандартный файл default_en.txt без добавленных вами определений. Что бы этого избежать, лучше собственные определения поместить в отдельный текстовой файл с произвольным именем, например, mydef.txt и загружать его в своих программах после импорта библиотеки и создания объекта класса UnitRegistry() с помощью команды:

>>>ureg.load_definitions('/your_path/mydef.txt')

При этом ваши определения добавятся к стандартным. Если же вы ходите получить только свои определения и не загружать стандартные (например, если вы переопределяете стандартную единицу измерения), то передайте свой файл конструктору объекта:

>>>ureg = UnitRegistry('/your_path/mydef.txt')`

Добавление определения единицы измерения непосредственно в программе

Вы можете легко добавлять единицы измерения, измерения или псевдонимы в реестр программным путем. Давайте добавим dog_year (иногда пишется как dy), эквивалентный 52 (человеческим) дням:

>>>from pint import UnitRegistry
>>>ureg = UnitRegistry()
>>>Q_ = ureg.Quantity

>>>#Здесь мы добавляем новую единицу
>>>ureg.define('dog_year = 52 * day = dy')

>>>#Далее создаём количественную переменную и переводим её в новые единицы
>>>lassie_lifespan = Q_(10, 'year')
>>>print(lassie_lifespan.to('dog_years'))

В результате получим: 70.24038461538461 dog_year. Обратите внимание, что мы использовали имя dog_years хотя мы не определили форму множественного числа как псевдоним. Модуль Pint заботится об этом, поэтому вам не нужно этого делать. Формы множественного числа, которые не просто строятся путем добавления суффикса "s" к форме единственного числа, должны быть явно указаны как псевдонимы (см., например, millennia)

Вот, что тут любопытно: если вместо формы множественного числа

>>>print(lassie_lifespan.to('dog_years'))

написать в единственном числе:

>>>print(lassie_lifespan.to('dog_year'))

результат будет тот же самый. Зачем это сделано? Не знаю... Вероятно, что бы следовать принципам Питона в стремлении к максимальному приближению к естественному языку.

Вы также можете добавить префиксы программным путем:

>>>ureg.define('myprefix- = 30 = my-')

где число указывает на коэффициент умножения.

То же самое для псевдонимов и производных размеров:

>>>ureg.define('@alias meter = metro = metr')
>>>ureg.define('[hypervolume] = [length] ** 4')

Некоторые единицы содержат константы. Они могут быть определены с помощью ведущего подчеркивания:

>>>ureg.define('_100km = 100 * kilometer')
>>>ureg.define('mpg = 1 * mile / gallon')
>>>fuel_ec_europe = 5 * ureg.L / ureg._100km
>>>fuel_ec_us = (1 / fuel_ec_europe).to(ureg.mpg)

ПРЕДУПРЕЖДЕНИЕ
Единицы измерения, префиксы и псевдонимы, добавленные программным путем, забываются при завершении работы программы.

Присоединение единиц измерения к числам и переменным и вычисления с ними

Пожалуй, это самое главное назначение модуля Pint. Он позволяет присоединять единицы измерения к операндам вычислений и автоматически получать единицу результата. Для присоединения единиц измерения к операнду математической операции, надо всего лишь умножить операнд на объект ureg:

>>>10 * ureg.kg +  20 * ureg.kg
 30 <Unit('kilogram')>

В данном примере мы сложили 10 килограммов и 20 килограммов и получили 30 килограммов. Т.е. Питон сработал чисто математически - он вынес ureg.kg за скобки и сложил 10 + 20. Но модуль Pint позволяет правильно прибавлять и граммы к килограммам:

>>>10 * ureg.kg + 300 * ureg.g
10.3 <Unit('kilogram')>

Если присвоить единицу измерения переменной, то она изменит свой тип на объект класса Quantity():

>>>distance = 24.0 # пока без единицы измерения
>>>type(distance)
float
>>>distance = distance * ureg.km # теперь distance равно 24 километра
>>>type(distance)
pint.quantity.build_quantity_class.<locals>.Quantity

Теперь обычная математика с переменной distance невозможна:

>>>distance + 3
DimensionalityError: Cannot convert from 'kilometer' to 'dimensionless'

Так же нельзя и прибавить несовместимую единицу:

>>>distance + 3 * ureg.g
DimensionalityError: Cannot convert from 'kilometer' ([length]) to 'gram' ([mass])

Разумно - сложение расстояния и массы не имеет физического смысла. А вот умножать, делить и возводить в степени переменные с разными единицами можно:

>>>distance = 24.0 * ureg.km # расстояние 24 км
>>>time = 3.0 * ureg.hour + 30.0 * ureg.minute # время 3 часа 30 минут
>>>speed = distance / time # скорость это действительно пройденное расстояние, делённое на затраченное время
>>>print(speed)
7.199999999999999 kilometer / hour # поэтому иы и получили километры в час
>>>acceleration = distance / time ** 2
>>>print(acceleration)
2.1599999999999997 kilometer / hour ** 2

Мы можем посмотреть, какую размерность у нас имеют результаты вычислений:

>>>print(speed.dimensionality)
[length] / [time]
>>>print(acceleration.dimensionality)
[length] / [time] ** 2

При вычислении ускорения получилось вроде и правильно, но как то непривычно видеть \frac{km}{h^2}. Можно преобразовать к более каноничным \frac{m}{s^2}:

>>>print(acceleration.to('m/s**2'))
0.00016666666666666663 meter / second ** 2

В последнем примере интересно не только простота преобразования единиц измерения (метод to() объектов класса Quantity()), но и новый способ представления единиц измерения - в виде строки. Этот способ работает не только при преобразовании величин, но и во всех других случаях применения модуля Pint. Например:

>>>distance = 24.0 * ureg('km')
>>>print(distance)
24.0 kilometer

Вообще оба способа представления единиц измерения взаимозаменяемы во всех случаях и могут как угодно комбинироваться в одном выражении. Например, видоизменим команду преобразования единицы:

>>>print(distance.to(ureg.m))
24000.0 meter

Объекты Quantity() также хорошо работают с массивами NumPy (соответственно, переменными с присоединенными единицами измерения можно использовать все функции математических модулей Numpy и Scipy) и таблицами Pandas

Выделение значения и единицы измерения

Как было выше сказано, после присоединения к переменной единицы измерения, переменная превращается в объект класса Quantity() и дальнейшая математика с ней возможна только с другими объектами класса Quantity() (величинами или переменными, имеющими совместимые единицы измерения). Строго говоря, это не совсем так. При необходимости из переменной (объекта) класса Quantity() можно выделить её значение в обычную переменную типа int или float. Это возможно благодаря тому, что у всех объектов класса Quantity() есть два свойства: magnetude и units - содержащие. соответственно, значение и единицу измерения:

>>>type(distance)
pint.quantity.build_quantity_class.<locals>.Quantity
>>>d = distance.magnitude
>>>type(d)
float
>>>print(distance.magnetude)
24.0
>>>print(distance.units)
kilometer

Упрощение единиц измерения

Иногда величина величины будет очень большой или очень маленькой. Метод to_compact() может корректировать единицы измерения, чтобы сделать количество более удобочитаемым для человека:

>>>wavelength = 1550 * ureg.nm # длина волны 1550 нанометров
>>>frequency = (ureg.speed_of_light / wavelength).to('Hz') # разделим скорость света на длину волны и приведём результат к герцам
>>>print(frequency)
193414489032258.03 hertz
>>>print(frequency.to_compact())
193.41448903225802 terahertz

193 терагерца воспринимается человеком более естественно и понятно, чем 193414489032258 герц

Существуют также методы to_base_units() и ito_base_units(), которые автоматически преобразуют несистемные единицы в эталонные единицы СИ правильной размерности:

>>>height = 5.0 * ureg.foot + 9.0 * ureg.inch
>>>print(height)
5.75 foot
>>>print(height.to_base_units())
1.7525999999999997 meter
>>>print(height)
5.75 foot
>>>height.ito_base_units()
>>>print(height)
1.7525999999999997 meter

Из примера видно, что разница между этими методами в том. что метод to_base_units() возвращет результат преобразования, а метод ito_base_units() изменяет саму переменную.

Модуль Pint может автоматически приводить результаты вычислений к эталонным единицам СИ. Для этого при создании объекта класса UnitRegistry надо передать конструктору параметр autoconvert_offset_to_baseunit = True.

Существуют также методы to_reduced_units() и ito_reduced_units(), которые выполняют упрощенное уменьшение размеров, объединяя единицы измерения с одинаковой размерностью и не затрагивая остальные единицы измерения:

>>>density = 1.4 * ureg.gram / ureg.cm ** 3
>>>volume = 10 * ureg.cc
>>>mass = density * volume
>>>print(mass)
14.0 cubic_centimeter * gram / centimeter ** 3
>>>print(mass.to_reduced_units())
>>>print(mass)
14.0 cubic_centimeter * gram / centimeter ** 3
>>>mass.ito_reduced_units()
>>>print(mass)
14.0 gram

Конечно, измерять массу в кубических сантиметрах и граммах неправильно. Учитывая, что cubic\_centimeter = centimeter^3, метод сокращает эти единицы и остаются правильные граммы.

Модуль Pint может автоматически сокращать единицы и упрощать результат. Для этого при создании объекта класса UnitRegistry надо передать конструктору параметр auto_reduce_dimensions = True.

Синтаксический анализ строк

Как уже было показано выше, ещиницы измерения объекту ureg можно передавать в виде строк. При этом содержимое строки может быть в достаточной степени произвольным. Всё дело в том. что модуль Pint содержит в себе мощный синтаксический анализатор строковых выражений. И его возможности не ограничиваются одним присоединением и преобразованием единиц измерения. Числа также анализируются, поэтому вы можете использовать выражение:

>>>ureg('2.54 * centimeter')
2.54 <Unit('centimeter')>

Можно так же использовать конструктор объекта класса Quantity:

>>>Q_ = ureg.Quantity
>>>Q_('2.54 * centimeter')
2.54 <Unit('centimeter')>

Более того, знак "*" можно опускать:

>>>Q_('2.54cm')
2.54 <Unit('centimeter')>

Это позволяет вам написать простой конвертер единиц измерения:

>>>user_input = '2.54 * centimeter to inch'
>>>src, dst = user_input.split(' to ')
>>>Q_(src).to(dst)
 1.0 <Unit('inch')>

Строки, содержащие значения, могут быть проанализированы более глубоко с помощью метода parse_pattern(). В качестве шаблона используется строка, подобная формату, с определенными в ней единицами измерения:

>>>input_string = '10 feet 10 inches'
>>>pattern = '{feet} feet {inch} inches'
>>>ureg.parse_pattern(input_string, pattern)
[10.0 <Unit('foot')>, 10.0 <Unit('inch')>]

Чтобы выполнить поиск нескольких совпадений, установите параметр many = True. Следующий пример демонстрирует, как анализатор может находить совпадения среди символов-заполнителей:

>>>input_string = '10 feet - 20 feet ! 30 feet.'
>>>pattern = '{feet} feet'
>>>ureg.parse_pattern(input_string, pattern, many=True)
[[10.0 <Unit('foot')>], [20.0 <Unit('foot')>], [30.0 <Unit('foot')>]]

Обратите внимание, что фигурные скобки ({}) преобразуются синтаксическим анализатором в шаблон сопоставления с плавающей точкой.

Эта функция полезна для таких задач, как массовое извлечение единиц измерения из тысяч однородных строк или даже очень больших текстов, в которых единицы измерения разбросаны без определенного шаблона.

Форматирование строк

Физические величины можно легко распечатать несколькими способами.

Стандартный код форматирования строки

>>>accel = 1.3 * ureg['meter/second**2']
>>>print('The str is {!s}'.format(accel))
print('The str is {!s}'.format(accel))

Стандартный код форматирования представления

>>>print('The repr is {!r}'.format(accel))
print('The repr is {!r}'.format(accel))

Доступ к полезным атрибутам

>>>print('The magnitude is {0.magnitude} with units {0.units}'.format(accel))
The magnitude is 1.3 with units meter / second ** 2

Модуль Pint также поддерживает форматирование с плавающей запятой для массивов Numpy:

>>>import numpy as np
>>>accel = np.array([-1.1, 1e-6, 1.2505, 1.3]) * ureg['meter/second**2']
>>>print('The array is {:.2f}'.format(accel))
The array is [-1.10 0.00 1.25 1.30] meter / second ** 2
>>>print('The array is {:+.2E~P}'.format(accel))
The array is [-1.10E+00 +1.00E-06 +1.25E+00 +1.30E+00] m/s²

Модуль Pint поддерживает f-строки Питона:

>>>accel = 1.3 * ureg['meter/second**2']
>>>print(f'The str is {accel}')
he str is 1.3 meter / second ** 2
>>>print(f'The str is {accel:.3e}')
The str is 1.300e+00 meter / second ** 2
>>>print(f'The str is {accel:~}')
The str is 1.3 m / s ** 2
>>>print(f'The str is {accel:~.3e}')
The str is 1.300e+00 m / s ** 2

Так же можно выводить строки в форматах HTML и LaTeX:

>>>accel = 1.3 * ureg['meter/second**2']
>>>print('The pretty representation is {:P}'.format(accel))
The pretty representation is 1.3 meter/second²
>>>print('The HTML representation is {:H}'.format(accel))
The HTML representation is 1.3 meter/second<sup>2</sup>
>>>print('The LaTeX representation is {:L}'.format(accel))
The LaTeX representation is 1.3\ \frac{\mathrm{meter}}{\mathrm{second}^{2}}

Если вы хотите использовать сокращенные названия единиц измерения, добавьте перед спецификацией префикс ~.

Спецификации форматирования (L, H и P) можно использовать с синтаксисом форматирования строк с плавающей точкой. Например, научная нотация:

>>>print('Scientific notation: {:.3e~L}'.format(accel))
Scientific notation: 1.300\\times 10^{0}\\ \\frac{\\mathrm{m}}{\\mathrm{s}^{2}}

Кроме того, вы можете указать спецификацию формата по умолчанию:

>>>ureg.default_format = 'P'
>>>print('The acceleration is {}'.format(accel))
The acceleration is 1.3 meter/second²

Комментарии (42)


  1. Dukarav
    13.08.2022 09:19
    +1

    надо бы упомянуть

    1

    2

    а так же ряд других решений в matcad, RUST и т.п.


    1. MAK74 Автор
      13.08.2022 13:50
      +2

      Не вижу смысла писать и о других решениях - статья ведь конкретно о Python. Тем более, что про RUST я вообще ничего не знаю


  1. buratino
    13.08.2022 10:33
    +2

    цикл туториалов,

    вызывает непреодолимое желание воспитать ссаными тряпками


    1. MAK74 Автор
      13.08.2022 12:45
      -1

      Ну воспитывай ;)


      1. buratino
        13.08.2022 16:02
        +3

        Если заявлено про материалы на русском языке и русскоязычные инженеры, то надо писать хотя бы в названии на русском языке, а не на не пойми каком


        1. Megakazbek
          13.08.2022 16:26

          Я так понимаю, что "материалы" и "инженеры" - это исконно русские слова?


          1. Javian
            13.08.2022 16:34
            +3

            "Туториал" отсутствует в словаре иностранных слов русского языка.


            1. Megakazbek
              13.08.2022 23:17

              Словарь - это археология языка, там написано то, каким язык когда-то был, и то в меру кругозора его составителей. Мало того, что абсолютно все слова языка невозможно выявить даже очень целеустремлённой группе авторов и часть слов в словарь так и не попадает, так к тому же в первую же секунду после публикации он начинает устаревать. А то, какой язык есть сейчас, можно понять только по тем словам, которые люди прямо сейчас используют, так как именно это определяет язык, а не словарь.


            1. invasy
              14.08.2022 13:31
              +1

              «Прескриптивизм» и «дескриптивизм» там есть?


  1. vadimr
    13.08.2022 11:18

    В качестве курсовой работы это нормально, но в реальной практике физические расчёты опираются на библиотеки вычислительных алгоритмов, которые ни о каких единицах измерения не имеют понятия, а зачастую и прямо нарушают их систему некоторыми численными приближениями.


    1. MAK74 Автор
      13.08.2022 12:45

      Как минимум после применения любых библиотек, надо добавить единицу измерения результата - иначе непонятно, слонов ты получил или паровозы. Но что бы не ошибиться, не запутаться и не делать кучу ручной работы, лучше единицы добавить в самом начале расчётов - фишка модуля pint именно в том, что дальше вы можете применять любые библиотеки вычислительных алгоритмов, при этом и единицы измерения будут правильно преобразовываться, а в случае если вычислительный алгоритм будет применен неверно с точки зрения обсчитываемого физического процесса - т.е. в результате вычисления вылезет несовместимая или несуществующая единица измерения, - то сразу получим исключение, не усугубляя дальше неправильный расчёт


      1. vadimr
        13.08.2022 13:21

        Половина численных методов основана на приближенных равенствах вроде x ≈ x**2 при x ≈ 1 и т.п. Естественно, единицы измерения при этом не сохраняются, и это не является признаком неправильного расчёта.

        Эти все фишки с единицами измерения дальше школьной арифметики не работают. Уже банальное разложение в ряд Тейлора - фундамент матанализа - не сохраняет единицы измерения в обыденном понимании (которое лежит в основе описываемой библиотеки). Надо было бы придумывать предельный переход бесконечной последовательности единиц измерения и т.п. А ряд Тейлора - это только один простой частный случай.


        1. MAK74 Автор
          13.08.2022 13:46

          Для расчётов с неопределённостями в Питоне тоже есть специальный модуль (и я как раз сейчас готовлю о нём статью для Хабра). И если в исходных данных были единицы измерения из модуля pint, то они тоже будут сохранены и правильно обработаны в результате.

          Что же касаемо арифметики - то вот она то как раз ни с какими единицами измерения не работает. В "чистой" математике всё равно, с чем ты имеешь дело. Но в физике и инженерии совершенно не так - тут нельзя применять математические методы таким образом, что бы в результате разложения паровоза получились слоны и канарейки. Вот для того, что бы контролировать физическую правильность математических выкладок, и предназначен модуль pint.


          1. vadimr
            13.08.2022 14:00

            Это очень упрощённое понимание физики и инженерии.

            Начните с того, что попробуйте ввести единицы измерения для бесконечно малых величин. Потом можно попробовать последовательно ввести единицы измерения в квантовую механику, и в итоге свести её в один математический аппарат с теорией относительности ;)


            1. MAK74 Автор
              13.08.2022 14:33

              Квантовая механика это совершенно особая тема. Я же писал об обычной инженерии, имеющей дело с макрообъектами, а не с микромиром


              1. vadimr
                13.08.2022 14:40

                Ну когда как. Сейчас квантовая электроника и квантовая оптика образуют вполне весомую часть в общем объёме инженерных расчётов. В России особенно квантовая оптика активно развивается.

                Но я не настаиваю именно на квантовой механике. Просто хочу сказать, что сложные физические расчёты – непростые вещи чисто в вычислительном отношении.


        1. Taus
          13.08.2022 16:31

          Фишки с единицами измерений как раз очень помогают. Если функция зависит сложным образом от величины X (сложнее степенной функции), то величина X должна быть безразмерной. К тому же, это является хорошей проверкой результата на ошибки после алгебраических преобразований.
          Наверное, единственная используемая функция, в которую мы подставляем размерную величину, - это логарифм, то есть dB и близкие к нему. Правильнее было бы вычислять логарифм отношения X к размерному референсному значению. Но, потом мы чаще сравниваем значения dB относительно друг друга, а не абсолютные.


          1. vadimr
            13.08.2022 16:38

            Если функция зависит сложным образом от величины X (сложнее степенной функции), то величина X должна быть безразмерной

            Это большое заблуждение. Допустим, величина X – это дальность в метрах по данным локации космического аппарата, а функция – большая полуось его орбиты тоже в метрах, построенная по результатам применения статистических фильтров к данным нескольких таких локаторов (с помехами), модели гравитационного поля Земли, модели атмосферы, и т.д. и т.п. Величина X может при этом даже и не войти в результат, если фильтр рассудит, что это помеха.

            Я чего-то даже сам задумался, какую размерность имеет измерение физической величины, умноженное на статистический весовой коэффициент. 100 километров с вероятностью 0.5 – это то же самое, что 50 километров, или всё же нет?

            Инженерная практика – это очень часто математическая статистика в том или ином виде.


            1. Taus
              13.08.2022 16:48
              +1

              Если функция требует подстановки значений в метрах, то в неё уже неявно зашита константа, которая приводит метры в безразмерную величину. Каким образом статистические фильтры могут влиять на размерность величины?

              100 километров с вероятностью 0.5 – это то же самое, что 50 километров, или всё же нет?

              Вероятность - безразмерная величина как раз для того, чтобы можно было её на что угодно умножать. "100 км с вероятностью 0.5" - это уже не просто число с размерностью, сама фраза имеет значение в каком-то контексте.


              1. vadimr
                13.08.2022 17:07

                Не понял Вашу реплику.

                Давайте для простоты возьмём конкретный пример. Мы измерили одно и то же расстояние 3 раза, первый раз получилась гипотеза 1 метр с апостериорной мощностью критерия 0.8, второй раз получилась гипотеза 1.2 метра с мощностью критерия 0.7, и третий раз получилась гипотеза 0.9 метра с мощностью критерия 0.9. Какую размерность в данном случае имеет байесовская оценка и собственно результат измерения?

                По Вашим словам (как я их понял) получается, что меряли метры, а получили безразмерный результат.


                1. Taus
                  13.08.2022 17:35
                  +1

                  Про байесовские методы обработки данных почти ничего не знаю. В случае когда вы все величины измеряете в метрах, то и результат измерения будет в метрах, дополненный информацией о распределении случайной величины.
                  Я же утверждаю, что после замены всех единиц измерения в примере с метров на, например, герц, включая шум, результат в числах не поменяется.


  1. kimor
    13.08.2022 12:47

    огромное количество различных библиотек (модулей), написанных как на самом питоне, так и на более быстрых "профессиональных" языках С/С++ и Фортран.

    Судя из написанного, Питон по мнению автора язык непрофессиональный. Дальше читать не стал.


    1. MAK74 Автор
      13.08.2022 12:49

      Я не программист - поэтому могу и ошибаться в том, что профессиональные программисты не пишут на Питоне операционные системы, антивирусы, компиляторы и прочие пакеты прикладных программ. Если обидел профессионала - приношу свои извинения. Но хотелось бы получить конкретные примеры профессиональных программных продуктов, написанных на Питоне...


      1. vadimr
        13.08.2022 13:39

        Ну уж, во всяком случае, побольше частей современных ОС написано на питоне, чем на фортране.


        1. MAK74 Автор
          13.08.2022 13:49

          Убедили. Убрал из аннотации "профессиональность"


        1. buratino
          13.08.2022 16:06

          ну назовите хотя бы одну часть ос, написанную на питоне.

          Только именно ос, а не приложения под ос


          1. vadimr
            13.08.2022 16:15

            Странный вопрос. find / -name "*.py"

            virt-manager, например, написан на питоне.


            1. buratino
              13.08.2022 19:42

              Какие буквы вам непонятны в "The virt-manager application is a desktop user interface"?


              1. vadimr
                13.08.2022 20:31
                -1

                А какие буквы вам непонятны в "часть ОС"? Это одна из важнейших частей пользовательского интерфейса операционной системы.


                1. buratino
                  13.08.2022 21:31
                  -1

                  читайте доки что есть application и что есть operating system

                  не говоря уже об утверждении, что virt-manager есть одна из важнейших частей пользовательского интерфейса


      1. kimor
        14.08.2022 12:22

        Как-то Вы очень странно понимаете смысл слова профессиональный. Профессиональный от слова профессия. Видимо, мы учили разные русские языки в школе...


        1. MAK74 Автор
          14.08.2022 12:45

          Может быть, может быть... Я, всё-таки, русский только на половину и всю жизнь прожил в Молдавии ;)


          1. kimor
            14.08.2022 12:49

            Гадая что Вы хотели сказать говоря "непрофессиональный", единственное что мне приходит в голову, что он используется только для обучения, как в настоящее время, например, Паскаль. Про Питон такого точно сказать нельзя. Старайтесь быть точнее в формулировках.


            1. MAK74 Автор
              14.08.2022 13:02

              Посыпаю голову пеплом, хотя сказать я хотел совсем не это. Я предполагал, что Питон (ввиду его простоты) используют не программисты, а специалисты других профессий, которым надо что-то быстро напрограммировать для своей работы (сам такой). Воспринимаю Питон как потомка Бейсика (до знакомства с Питоном, я для тех же целей использовал VB6/VBA/VBS).


  1. proton17
    13.08.2022 12:57
    +1

    Было интересно, но название не совсем отражает смысл публикации. И точно не говорит о том, что это первая статья цикла. Тогда уж что-то типа «Применение языка Python в инженерной практике. Часть 1 — обзор модуля Pint».


    1. MAK74 Автор
      13.08.2022 13:47

      Предложение принимается


  1. alt78
    13.08.2022 17:29

    Пробовал использовать pint в работе, впечатления негативные.. Я иногда делаю физические расчеты. Пробовал делать их с pint, неудобно - громоздкий вывод, код распухший. Это оправдано только если код в прод, если надо быстро что-то проверить - неудобно.

    Вернулся в SMath.


    1. MAK74 Автор
      14.08.2022 12:56

      Не могу с Вами не согласиться ;) Привыкшему к  WYSIWYG сложно от него отказаться. Сам до сих пор до конца от MathCAD не отказался


  1. mixas-f
    14.08.2022 13:03

    Не очень понятно, на какую аудиторию эта статья рассчитана? Если на школьника, то есть куча роликов, куда более наглядных. А для студента - материал вроде бы чересчур примитивен. Или я не прав?


    1. MAK74 Автор
      14.08.2022 13:09

      Я рассчитывал не на школьника и не на студента - а на такого же инженера непрограммистской специальности, которым являюсь и сам. Которому, тем не менее, в работе периодически надо что-то по-быстрому посчитать.

      Что же касаемо кучи роликов, то я их как раз не люблю смотреть - привык пользоваться печатной документацией. Хотя бы потому, что из ролика код невозможно скопипастить ;) И предполагаю, что я не один такой


  1. red_dragon
    14.08.2022 16:07

    193 терагерца воспринимается человеком более естественно и понятно, чем 193414489032258 герц..

    Вот тут прямо долго силился понять. Если всё, что после 193 не значимо, почему не использовать экспоненциальную запись 193Е14. Если же Вы считаете, что положение точки в числе, влияет на его читаемость, то это очень спорно.


  1. sargon5000
    15.08.2022 06:46

    Насчёт т определения метра автор здорово заблуждается. Метр — длина пути, проходимого светом в вакууме за интервал времени 1⁄299 792 458 секунды