Рубрики
Без рубрики

Легко читать код с неизменными значениями (Pyrsistent).

TLDR: используйте структуры данных, которые не изменяются после создания (используя Pyrsistent), чтобы облегчить … Теги с функционалом, Python.

TLDR:

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

Цель.

Когда структура данных (например, Dict) после создания, не изменяется, это позволяет нам читать код с большим уверенностью.

Для е.Г. Допустим, у вас есть Клиент Переменная в вашем коде, и вы отслеживаете его значение, читая код. Что вы причина, это ценность Клиент ниже?

customer = dict(name="Rajiv", age=40)
some_function(customer)
print(customer)

В приведенном выше коде мы не можем сказать. В Python, для большинства структур данных по умолчанию, таких как обдумывать , возможно, что Некоторые_функция мог бы изменить значение Клиент Отказ Итак, мы должны копаться и прочитать код Некоторые_функция быть полностью уверенным. Если код Некоторые_функция был ниже:

def some_function(a):
    a1 = a
    a1['name'] = 'NewRajiv' # Changing the values. blasphemy
    # do something with a1

тогда Печать (клиент) будет отображаться {«Имя»: «Ньюраджив», «Возраст»: 40} Отказ

Если вам повезет, Некоторые_функция Не пропускает его вперед к другим функциям! Или иначе вам придется копать и прочитать эти функции тоже:). Теперь это будет сосать. Разве это не намерение, что Клиент Поле должно быть мутировано, но в большинстве случаев человек не ожидает, что он должен быть таким (на других языках, обозначение обозначений, которые используются для указания, если это именно). Знающий программист может сделать копию (через copy.deepcopy () ) и работать на копии, чтобы предотвратить затрагивание ее кода, но я не был таким осведомленным программистом:)

Что, если мы могли бы использовать структуру данных, которая когда-то создана, не может быть изменена I.E. Это неизменяется. Давайте проверим библиотеку под названием пирсастент Это дает нам такие структуры данных.

from pyrsistent import m # m is like a dictionary

customer1 = m(name='Rajiv', age=40)
customer2 = customer1.set(name='NewRajiv')
print(customer1) # pmap({'age': 40, 'name': 'Rajiv'})
print(customer2) # pmap({'age': 40, 'name': 'NewRajiv'})

Когда мы указываем другое значение («Newrajiv»), копия создается с этим новым значением и назначена клиент2 . Customer1 все еще сохраняет значение, которое он был впервые назначен. Теперь вернемся к нашему предыдущему примеру кода и немного измените его для пирсастентность

from pyrsistent import m # m is like a dictionary

def some_function(a):
    a1 = a.set('name', 'NewRajiv')
    # do something with a1 

customer = m(name="Rajiv", age=40)
some_function(customer)
print(customer)


Печать (клиент) будет отображаться {«Имя»: «Раджив», «Возраст»: 40} , значение, установленное в нашем коде. Итак, мы можем благополучно рассуждать о нашем коде и что он делает, не беспокоясь об этом, меняющихся внутри Некоторые_функция Отказ Нам не нужно даже смотреть на Некоторые_функция в этом случае. Поверьте мне, когда вы не можете запустить этот фрагмент кода, чтобы увидеть, какие фактические значения, эта функция делает жизнь так проста:).

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

Из пирсастойственных документов:

from pyrsistent import v  # like a list

a = v(1, 2, 3)
b = a.append(4)

print(b[1])  # 2
print(b[1:3])  # pvector([2, 3])
print([2 * x for x in b])  # [2, 4, 6, 8]

На скорости и памяти

Я упростил (хорошо, я солгал), когда я сказал, что пирсастент делает копию структуры данных. Такая практика была бы пустой тратой памяти и времени, если мы копируем каждую огромную структуру данных. пирсастент Смягчает это в значительной степени, не просто вслепую копирование структур данных, а затем делать модификации. Он пытается быть умным по Распределение общей части между оригинальной структурой данных и новой модифицированной копией для экономии памяти и времени.

Давайте возьмем пример (кредит: Wikipedia: постоянные структуры данных). Ах, вы сейчас подвергаетесь тому, что это действительно называется. Эта концепция называется постоянные данные структуры или Функциональные данные структуры Отказ

ПРИМЕЧАНИЕ: Ниже приведен пример просто для объяснения концепций и такое двоичное дерево поиска не является частью пирсастент Отказ

Допустим, у вас было двоичное дерево поиска ( XS ), которая была постоянной структурой данных:

Теперь, если вы добавили узел е к этой структуре данных, например Ys (XS, E) Наивная реализация будет скопировать структуру данных, а затем вставить е в соответствующем месте. В подходе настойчивой структуре данных это было бы:

С е падает в правую сторону дерева (то есть. Дерево с g Как корневой), дерево с корнем B не затронут и, следовательно, может быть повторно используется. Вы можете увидеть стрелку из D ' к B указывает на это.

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

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

Примечание на Примечание: пирсастент пытается быть как можно быстрее и имеет сопоставимые скорости к норме для большинства случаев. Сложность большинства операций хорошо описана в своих документах.

Вложенные преобразования

Что если мы должны обновить вложенное значение в структуре данных при сохранении неподумности. пирсастент имеет метод трансформировать для этого. Как обычно это делаю

import copy
m4 = dict(a=1, b=6, c=[1, 2])
# I want to update c[1] to 17
m4_new = copy.deepcopy(m4) 
m4_new['c'][1] = 17

От своих документов,

from pyrsistent import m  # m is like a dictionary
from pyrsistent import v # m is like a list
m4 = m(a=5, b=6, c=v(1, 2))
m4_new = m4.transform(('c', 1), 17)
print(m4_new) # pmap({'a': 5, 'c': pvector([1, 17]), 'b': 6})

Обновление словарей

Одна вещь, которую я делаю очень часто, это слияние словарей. Для E.g. мне, возможно, придется построить свою конфигурацию, принимая следующие источники с самым ранним предшественником наивысшего приоритета.

  • Переменные среды
  • Конфигурация файла
  • Конфигурация по умолчанию

Как бы я обычно делал это.

default_conf = dict(database_url='dev_url', user='postgres', port=5432)
# Imagine file_conf below was extracted from a file
file_conf = dict(user='test_user', port=5433)
# Imagine env_conf below was constructed from environment variables
environment_conf = dict(database_url='test_url')
final_conf = {**default_conf, **file_conf, **environment_conf}

print(final_conf) # {'database_url': 'test_url', 'user': 'test_user', 'port': 5433}

Это здорово для 99% случаев, которые я думаю:). Но ради обсуждения, возможно, если у вас были огромные словари (например. Объединение всех данных, которые вы перешли незаконно с некоторых сайтов;)), это было бы некоторое дублирование данных в памяти. В пирсастент :

from pyrsistent import m
default_conf = m(database_url='dev_url', user='postgres', port=5432)
# Imagine file_conf below was extracted from a file
file_conf = m(user='test_user', port=5433)
# Imagine env_conf below was constructed from environment variables
environment_conf = m(database_url='test_url')
final_conf = default_conf + file_conf + environment_conf

print(final_conf) # pmap({'database_url': 'test_url', 'user': 'test_user', 'port': 5433})

Я надеюсь, что этого достаточно, чтобы вы начали в лучшем опыте кодирования:). Есть много других замечательных особенностей пирсастент Как и наличие вышеуказанного поведения для записей ( PRRECORD ) и CLASES ( PCLASS ) И многие более продвинутые функции. Я оставлю это для другого поста.

Так что отправляйтесь на пирсастент и проверьте это. И если вам это нравится, не забудьте звездить! Это замечательная техника, чья авторы которых мы должны аплодировать и поддерживать.

Оригинал: “https://dev.to/rabraham/reading-code-easily-with-immutable-values-pyrsistent-33eh”