Есть два рода людей, которые обычно имеют общий Сложность При запуске Python: те, кто узнает его без предыдущего опыта кодирования и тех, кто приходит с низкоуровневого программирования. Я подпадаю под вторую категорию, и когда дело доходит до определенных проблем, я знаю, мы склонны игнорировать возможные собственные решения и пытаться решить их в алгоритмическом способе. Это приятно (и лучше) для обучения, но языки высокого уровня обычно предлагают решения, которые будут легче кодировать, понимать и поддерживать.
Я предполагаю, что вы понимаете списки, словари и множества в Python и основы алгебры.
Содержание
- Список, словарь и заданное понимание
- Установить операции
- Наборы наборов
functools
модульfunctools.reduce.
functools.lru_cache.
Список, словарь и заданное понимание
Допустим, у нас есть список, содержащий некоторые числа, и мы хотим извлечь из него только даже в отдельный список. Совершенно действительный подход будет:
mylist = [5,4,3,7,8,1,12] even = [] for n in mylist: if (n%2 == 0): even.append(n) print(even) # [4,8,12]
Это довольно стандартный для языков С-семейства C-семейства. Тем не менее, самый питон способ использовать Понимание списка :
mylist = [5,4,3,7,8,1,12] even = [x for x in mylist if x%2 == 0] print(even) # [4,8,12]
Понимание списка является способом указания содержимого нового списка выражением и необязательным условием, связанным с элементами объекта ITERABLE. Синтаксис следующий:
# without filter [expression for element in sequence] # with filter [expression for element in sequence if condition]
Таким образом, другой пример может быть скопировать список строк, изменяя все их в верхний регистр:
names = ['Mikkel', 'Jonas', 'Martha'] uppernames = [name.upper() for name in names] print(uppernames) # ['MIKKEL','JONAS','MARTHA']
Теперь вы также можете определить наборы и словари по пониманию:
# sets set(expression for element in sequence) {expression for element in sequence} # dicts (note here's a difference in the key value specification) dict((key,value) for element in sequence if condition) {key:value for element in sequence if condition}
Но есть больше! Вам не нужно повторять только одну последовательность. Python позволяет добавлять больше, чем один Для <последовательности>
в ваших пониманиях. Давайте посмотрим некоторые примеры:
# dictionary merge merged = {k:v for (k,v) in dict1 for (k,v) in dict2} # cartesian product of two sets # - note that the result is not a dict, but a set of tuples cartesian = {(x,y) for x in set1 for y in set2}
Здесь Вы найдете больше примеров в списке, Dict и установленных возможностях.
Установить операции
Теперь с заданным пониманием легко определить обычные операции между наборами. Тем не менее, Python уже определяет эти операции в результате чего:
abcde = {'a','b','c','d','e'} vowels = {'a','e','i','o','u'} intersection = abcde & vowels # {'a','e'} union = abcde | vowels # {'a', 'b', 'c', 'd', 'e', 'i', 'o', 'u'} difference = abcde - vowels # {'b','c','d'} symmetricDifference = abcde ^ vowels # {'b','c','d','i','o','u'}
Обратите внимание, что вывод не должен быть отсортирован, но я написал это таким образом, чтобы облегчить понять.
Теперь существуют не только операции, которые приводят к новым комплектам, но и логическими операторами, такие как:
isStrictSubset1 = abcde < abcde # False isStrictSubset2 = difference < abcde # True isSubset1 = abcde <= vowels # False isSubset2 = abcde <= abcde # True isSubset3 = difference <= abcde # True isEmptySet = bool(abcde) # False isEmptySet = bool(abcde - abcde) # True
Наборы наборов
Ограничение иметь в виду при работе с наборами в Python в том, что наборы могут содержать только одновременные типы (INT, CHAR, TVES …) и сами настраиваются несомненно. По этой причине, если вы хотите хранить набор наборов, вы должны использовать вместо списка наборов. К счастью, на этот раз список пополнений в списке «Список» могут сделать его для замены заданных операций.
set1 = [{1,2,3}, {'a','b','c'}, {'A','B','C'}] set2 = [{'a','b','c'}, {'b','c'}, {'c'}] intersection = [x for x in set1 if x in set2] # [{'a','b','c'}] difference = [x for x in set1 if x not in set2] # [{1,2,3}, {'a','b','c'}, {'A','B','C'}] union = set2 + difference # [{'a', 'b', 'c'}, {'b', 'c'}, {'c'}, {1, 2, 3}, {'A', 'B', 'C'}] # You get the idea
Модуль Functools.
Это полезный модуль Python, который обеспечивает очень интересные утилиты, из которых я расскажу только о двух: Уменьшить
и @lru_cache
Отказ
Здесь Вы найдете полную официальную документацию по этому модулю.
functools.reduce.
Уменьшить
Очень мощный инструмент, поскольку он может обобщать практически любые (если не все) итеративные процессы в списке, и я настоятельно рекомендую вам погрузиться глубже в своем использовании. С целью этого поста я просто буду использовать его, чтобы обобщить операции между неопределенным количеством множеств.
Допустим, у нас такой же список множеств, как и раньше, и мы хотим сделать союз всех из них. Допустимый подход будет:
set1 = [{1,2,3}, {'a','b','c'}, {'A','B','C'}] union = set() for x in set1: union = union | x
Но с уменьшением точного же поведения получается как следует:
set1 = [{1,2,3}, {'a','b','c'}, {'A','B','C'}] union = functools.reduce(set.union, set1) # {1, 2, 3, 'a', 'A', 'b', 'c', 'B', 'C'}
Первый аргумент – это функция для применения, а вторая – это список, к которому он будет применен, в накопленном виде. Обратите внимание, что я не использовал оператора |.
как прежде. Вместо этого мне пришлось использовать названную функцию Set.union
Отказ Чтобы найти именованные функции, соответствующие набору операторов, вы можете ввести Помощь (набор)
в вашей консоли Python.
@ functools.lru_cache.
Как вы можете себе представить, хотя состоится легко напечатать и понимать, они не именно дешевы в вычислении. Модуль functools
Предоставляет нам несколько способов кэшировать результаты функции (обратите внимание, что аналогичное поведение получается для методов класса с @ functools.cached_property
).
@functools.lru_cache def count_vowels(sentence): sentence = sentence.casefold() return sum(sentence.count(vowel) for vowel in 'aeiou')
С такой простой аннотацией выше определения функции несколько вызовов будут хранить свой результат, если они снова вызываются, чтобы вернуть его вместо того, чтобы снова выполнить один и тот же код.
Это полезно не только для вычислительных дорогих функций, которые не изменится результат, но и для рекурсивных функций, которые будут повторяться. Например:
@functools.lru_cache def factorial(n): return n*factorial(n-1) if n else 1
Практический пример
Посмотрим, как это применяется, например, для отслеживания знакомых отношений.
import functools # https://en.wikipedia.org/wiki/Transitive_closure def transitiveClosure(relation): closure = relation while True: delta = {(x,y) for (x,r1) in closure for (r2,y) in closure if r1 == r2} newClosure = closure | delta if newClosure == closure: break closure = newClosure return closure; # Direct descendance information childRelation = { ('Martha','Ulrich'), ('Mikkel','Ulrich'), ('Magnus','Ulrich'), ('Mads','Tronte'), ('Ulrich','Tronte'), ('Tronte','Agnes'), ('Jonas','Hannah'), ('Jonas','Michael')} descendantRelation = transitiveClosure(childRelation) # Some functions using our new relation @functools.lru_cache def ancestorsOf(x): return {b for (a,b) in descendantRelation if a==x} def isDescendantOf(x,y): return y in ancestorsOf(x) def areRelated(peopleList): ancestors = [ancestorsOf(x) for x in peopleList] commonAncestors = functools.reduce(set.intersection, ancestors) return bool(commonAncestors) print(ancestorsOf('Martha')) # {'Agnes','Tronte','Ulrich'} print(isDescendantOf('Jonas', 'Agnes')); # False print(isDescendantOf('Martha', 'Agnes')); # True print(areRelated(['Martha', 'Jonas'])); # False print(areRelated(['Martha', 'Magnus', 'Mikkel'])); # True
Я надеюсь вы найдете эту информацию полезной. У вас есть какие-либо советы, которые вы хотите поделиться? Если у вас есть опыт решения ваших математических заданий с Python (или любым другим языком) Я хотел бы прочитать их!
Оригинал: “https://dev.to/miguelmj/beginner-tips-to-do-algebra-in-python-477e”