Скрытые возможности Python

Какие менее известные, но полезные функции языка программирования Python?

  • Попробуйте ограничить ответы ядром Python.
  • Одна функция на ответ.
  • Приведите пример и краткое описание функции, а не просто ссылку на документацию.
  • Обозначьте объект, используя заголовок в первой строке.

Быстрые ссылки на ответы:

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1 417
0
691 883
191

Ответы 191

Основные сообщения :)

import this
# btw look at this module's source :)

Расшифрованный:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Люблю источник для этого: D

Teifion 19.09.2008 15:58

Есть идеи, почему источник был зашифрован таким образом? Это было просто для развлечения или была какая-то другая причина?

MiniQuark 14.12.2008 23:32

способ написания источника идет вразрез с дзеном!

hasen 01.01.2009 08:39

Было бы легче понять, если бы вместо 65 он использовал ord ("A"), ord ("a") вместо 97 и ord ("z") - ord ("a") вместо 26. Остальное просто шифр Цезаря по 13 (AKA ROT13). Но на самом деле было бы более питонично использовать метод str.translate :-p

fortran 25.06.2009 16:39

Я обновил свой /usr/lib/python2.6/this.py, заменив старый код этим print s.translate("".join(chr(64<i<91 and 65+(i-52)%26 or 96<i<123 and 97+(i-84)%26 or i) for i in range(256))), и теперь он выглядит намного лучше !! :-D

fortran 25.06.2009 17:12

год, это называется иронией. (причина, почему они это сделали)

Joschua 11.03.2010 19:36

@MiniQuark: краткий урок истории: wefearchange.org/2010/06/import-this-and-zen-of-python.html

user21037 14.07.2010 04:51

Я на днях нашел эту историю import this. Достаточно интересно: wefearchange.org/2010/06/import-this-and-zen-of-python.html

asmeurer 28.12.2010 08:18

@ Дэн: Черт. Я не видел вашего комментария до сих пор.

asmeurer 28.12.2010 08:19
hg.python.org/cpython/file/tip/Lib/this.py
Janus Troelsen 03.02.2012 22:45

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

Jonathan Hartley 11.02.2012 15:14

Составьте список

составить список

Сравните более традиционные (без понимания списка):

foo = []
for x in xrange(10):
  if x % 2 == 0:
     foo.append(x)

к:

foo = [x for x in xrange(10) if x % 2 == 0]

Каким образом понимание списков является функцией скрытый Python?

Eli Bendersky 19.09.2008 15:56

Они, вероятно, «спрятаны» для бывших программистов на C и Java, которые раньше не видели таких возможностей, не думайте их искать и игнорируйте, если они увидят это в учебнике. OTOH программист на Haskell это сразу заметит.

finnw 19.09.2008 16:02

Вопрос действительно требует «пример и краткое описание функции, а не просто ссылку на документацию». Есть ли шанс добавить один?

Dave Webb 19.09.2008 16:35

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

ConcernedOfTunbridgeWells 02.01.2009 22:00

Если бы это была скрытая функция python, сегодня на python было бы написано на 40% больше строк кода.

Vasil 17.03.2009 04:04

Мне потребовалось возраст, чтобы найти понимание списков в Python. Конечно, сейчас без них жить не могу ...

Chinmay Kanchi 14.01.2010 01:07

+1 Думаю, стоит упомянуть и о вложенных списках: stackoverflow.com/questions/1198777/…

inspectorG4dget 22.09.2010 07:37

Метаклассы

конечно :-) Что такое метакласс в Python?

Специальные методы

Абсолютная сила!

Это моя любимая вещь в Python. Я особенно операторы перегрузки люблю. ИМХО object1.add(object2) всегда должен быть object1 + object2.

fncomp 10.03.2011 00:50

Я воспринимаю object1.add () как деструктивную операцию, а + как операцию, возвращающую результат без изменения object1.

XTL 16.02.2012 14:00

Создание объектов-генераторов

Если вы напишете

x=(n for n in foo if bar(n))

вы можете достать генератор и назначить его x. Теперь это означает, что ты можешь сделать

for n in x:

Преимущество этого в том, что вам не нужно промежуточное хранилище, которое вам понадобилось бы, если бы вы

x = [n for n in foo if bar(n)]

В некоторых случаях это может привести к значительному ускорению.

Вы можете добавить множество операторов if в конец генератора, в основном реплицируя вложенные циклы for:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)

Вы также можете использовать для этого понимание вложенного списка, да?

shapr 05.05.2009 20:53

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

saffsd 17.05.2009 06:41

Я использую ifilter для таких вещей: docs.python.org/library/itertools.html#itertools.ifilter

Dan 31.03.2010 08:48

Это не особо "скрытый" imo, но также стоит отметить тот факт, что вы не можете перематывать объект генератора, тогда как вы можете повторять по списку любое количество раз.

susmits 15.04.2010 20:26

то же подозревает. Хотя это очень круто, это задокументированная функция Python docs.python.org/tutorial/classes.html. Использование обратных вызовов с вашими генераторами, также задокументированное, делает генераторы более крутыми. python.org/dev/peps/pep-0255

Justin 28.05.2010 19:22

Функция генераторов «без перемотки» может вызвать некоторую путаницу. В частности, если вы распечатываете содержимое генератора для отладки, а затем используете его позже для обработки данных, это не сработает. Данные производятся, потребляются print () и становятся недоступными для нормальной обработки. Это не относится к составным спискам, поскольку они полностью хранятся в памяти.

johntellsall 28.05.2010 20:01

Аналогичный (дубли?) Ответ: stackoverflow.com/questions/101268/hidden-features-of-python‌ /… Обратите внимание, однако, что в ответе, который я здесь связал, упоминается ДЕЙСТВИТЕЛЬНО ХОРОШАЯ презентация о мощности генераторов. Тебе действительно стоит это проверить.

Denilson Sá Maia 05.08.2010 00:21

Вот хорошая статья об использовании генератора для решения реальных проблем dabeaz.com/generators/Generators.pdf

OnesimusUnbound 04.02.2011 15:04

Декораторы

Декораторы позволяет заключить функцию или метод в другую функцию, которая может добавлять функциональные возможности, изменять аргументы или результаты и т. д. Вы пишете декораторы на одну строку над определением функции, начиная со знака «at» (@).

В примере показан декоратор print_args, который печатает аргументы декорированной функции перед ее вызовом:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo

При определении декораторов я бы рекомендовал украсить декоратор @decorator. Он создает декоратор, который сохраняет сигнатуру функции при интроспекции. Подробнее здесь: phyast.pitt.edu/~micheles/python/documentation.html

sirwart 22.09.2008 19:53

Как это скрытая функция?

Vetle 02.10.2008 17:52

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

DzinX 03.10.2008 10:51

vetler, вопросы касаются «менее известных, но полезных функций языка программирования Python». Как вы оцениваете «менее известные, но полезные функции»? Я имею в виду, какие из этих ответов скрыты?

Johnd 24.05.2009 01:14

@vetler Большинство вещей здесь вряд ли "спрятано".

Humphrey Bogart 06.04.2010 19:33

Скрытый? это задокументированная функция python.org/dev/peps/pep-0318

Justin 28.05.2010 19:26

Если стандарт заключается в том, задокументирована ли функция, то этот вопрос следует закрыть.

Jesse Dhillon 26.07.2010 03:08

Я думал, что мы должны перечислить скрытые функции python, а не удивительные возможности python. ;-)

Kamil Szot 23.01.2011 23:49

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

Dexter 04.02.2011 00:49

@Dexter: потому что этот декоратор может быть универсальным - его можно на короткое время прикрепить к любой функции, например когда нужно его отладить, то очень легко удаляется. Кроме того, декораторы могут использоваться не только для отладки.

DzinX 07.02.2011 19:29

Украсить декоратора декоратором-декоратором? Мы должны пойти глубже.

Casey Rodarmor 15.01.2012 11:45

Что касается полезных (спорных), то несколько более распространенных: @ property, @ classmethod, @ staticmethod, @ coroutine, @ _o (monocle)

XTL 16.02.2012 11:39

Декораторы чрезвычайно удобны, но они могут быть PITA для написания. Существует так много вариантов - на основе классов и не на основе классов, декораторы, которые могут украшать методы и функции (или и то, и другое), добавлять дескрипторы, декораторы, принимающие аргументы, и т. д. Таким образом, хотя приведенный выше простой пример не может быть «скрытой» функцией Python, я бы сказал, считайте его отправной точкой для изучения довольно сложной темы языка, и он должен быть в списке.

Adam Parkin 23.02.2012 21:31

Читаемые регулярные выражения

В Python вы можете разбить регулярное выражение на несколько строк, назвать совпадения и вставить комментарии.

Пример подробного синтаксиса (из Погрузитесь в Python):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

Пример совпадения имен (из Регулярное выражение HOWTO)

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

Вы также можете подробно написать регулярное выражение без использования re.VERBOSE благодаря конкатенации строковых литералов.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

Я не знаю, действительно ли я считаю, что это функция Python, у большинства двигателей RE есть подробный вариант.

Jeremy 22.09.2008 00:44

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

Mark Baker 17.10.2008 13:08

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

Berk D. Demir 22.03.2009 16:18

Я бы предпочел просто сказать: 100 = "(CM | CD | D? C {0,3})" # 900 (CM), 400 (CD) и т. д. В языке уже есть способ давать имена объектам, способ добавления комментариев и способ объединения строк. Зачем использовать здесь специальный синтаксис библиотеки для вещей, с которыми язык уже отлично справляется? Похоже, это прямо противоречит 9-й эпиграмме Перлиса.

Ken 05.05.2009 22:19

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

Roger Pate 28.06.2009 02:30

Если вы пишете программу на Python, а ваш файл конфигурации не является Python, тогда (Йегге сказал бы, и я согласен с этим) «вы говорите обоими устами», как OO: sites.google.com/site/steveyegge2/the-emacs-problem

Ken 27.05.2010 01:01

Отлично! При конкатенации строковых литералов комментарии анализируются как фактические.

asmeurer 28.12.2010 08:11

Я начинаю свои подробные шаблоны с (?x) # Use verbose mode, который кажется более самодокументированным, чем использование re.VERBOSE на этапе компиляции. Это должны быть самые первые символы в шаблоне - без ведущих пробелов. Кроме того, при использовании подробного шаблона не забудьте указать \s или [ ] для обозначения пробелов (в зависимости от того, хотите ли вы захватить все пробелы или только пробелы). Об этом легко забыть при преобразовании стандартных шаблонов в подробные.

jwhitlock 07.02.2011 23:04

+1 для конкатенации строковых литералов, но -1 для Python даже с флагом re.VERBOSE, что, как мне кажется, приводит к ужасно читаемому коду.

orokusaki 01.02.2012 07:36

Понятия вложенных списков и выражения генератора:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

Они могут заменить огромные фрагменты кода вложенного цикла.

"for j in range (i)" - это опечатка? Обычно вам нужны фиксированные диапазоны для i и j. Если вы обращаетесь к 2-мерному массиву, вы упустите половину своих элементов.

Peter Gibson 29.03.2009 06:27

В этом примере я не обращаюсь к каким-либо массивам. Единственная цель этого кода - показать, что выражения из внутренних диапазонов могут обращаться к выражениям из внешних. Побочный продукт - это список пар (x, y) таких, что 4> x> y> 0.

Rafał Dowgird 30.03.2009 12:23

вроде как двойное интегрирование в исчислении или двойное суммирование.

Yoo 30.09.2009 00:57

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

sykora 26.01.2010 14:17

Чтобы добавить к комментарию Сикоры: представьте, что вы начинаете со стека for и if с yield x внутри. Чтобы преобразовать это в выражение генератора, сначала переместите x, удалите все двоеточия (и yield) и заключите все это в круглые скобки. Вместо этого, чтобы сделать список понятным, замените внешние скобки квадратными скобками.

Ken Arnold 14.06.2011 05:30

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

Profane 21.08.2011 21:30

Функции получения в операторе модуля

Функции attrgetter() и itemgetter() в модуле operator могут использоваться для создания функций быстрого доступа для использования при сортировке и поиске объектов и словарей.

Глава 6.7 в документации библиотеки Python

Этот ответ заслуживает хороших примеров, например, в сочетании с map().

Jonathan 29.08.2011 11:04

Отправка значений в функции генератора. Например, имея эту функцию:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

Вы можете:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7

Согласовано. Давайте рассматривать это как неприятный пример скрытой функции Python :)

Rafał Dowgird 19.09.2008 17:41

На других языках я считаю, что это волшебное устройство называется «переменной».

finnw 05.05.2009 21:49

сопрограммы должны быть сопрограммами, и генератор тоже должен быть самим собой, без смешивания. Мега отличная ссылка, а также обсуждение и примеры по этому поводу здесь: dabeaz.com/coroutines

u0b34a0f6ae 24.08.2009 01:39

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

Jim Dennis 24.06.2010 08:07

Это слишком банальный пример для людей, которые никогда не видели (и, вероятно, не поймут) сопрограмм. Пример, который реализует скользящее среднее без риска переполнения переменной суммы, является хорошим.

Prashant Kumar 11.06.2011 10:16

Подробнее о доходности здесь: stackoverflow.com/questions/231767/…

gecco 20.10.2011 22:59

@finnw и его сторонники, я думаю, вы неправильно поняли суть этого экзамена. Важным битом является не сохранение значения в 'a', это то, что 'mygen' действует как функция с несколькими точками входа и с возможностью приостановить выполнение на полпути и вернуть значение вызывающей стороне, но затем возобновить выполнение. позже, из той же точки, со всеми локальными переменными без изменений. Подробнее о них можно прочитать здесь en.m.wikipedia.org/wiki/Coroutine

Jonathan Hartley 11.02.2012 14:37

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

Создание тестовой оснастки, которая предоставляет классы с теми же интерфейсами, что и объекты, которыми будет управлять тестируемый код (субъекты нашего тестирования), называется «Mocking» (они называются «Mock Classes», а их экземпляры - «Имитация объектов»).

Jim Dennis 24.07.2010 03:17

>>> x=[1,1,2,'a','a',3]
>>> y = [ _x for _x in x if not _x in locals()['_[1]'] ]
>>> y
[1, 2, 'a', 3]


"locals () ['_ [1]']" - это "секретное имя" создаваемого списка. Очень полезно, когда состояние создаваемого списка влияет на последующие решения по сборке.

Фу. Это «имя» списка результатов зависит от слишком многих факторов, поэтому его нельзя рассматривать больше, чем злоупотребление конкретной реализацией (и специфической для конкретной версии для загрузки). Кроме того, это алгоритм O (n ^ 2). Фу.

Thomas Wouters 19.09.2008 17:31

Что ж, по крайней мере, никто не будет утверждать, что это не спрятано.

I. J. Kennedy 13.10.2010 02:35

Аргумент шага в операторах среза. Например:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

Особый случай x[::-1] - полезная идиома для «x, перевернутый».

>>> a[::-1]
[5,4,3,2,1]

На мой взгляд, гораздо понятнее функция reversed (). >>> список (обратный (диапазон (4))) [3, 2, 1, 0]

Christian Oudard 02.01.2009 21:35

тогда как лучше написать "this i a string" [:: - 1]? перевернутый, похоже, не помогает

Berry Tsakala 22.06.2009 00:56

"" .join (обратное ("это строка"))

erikprice 23.06.2009 21:17

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

Rafał Dowgird 24.06.2009 18:08

def reverse_string (строка): строка возврата [:: - 1]

pi. 03.02.2010 12:42

@pi Я думаю, что если кто-то знает достаточно, чтобы определить reverse_string, как у вас, то можно оставить [:: - 1] в своем коде и быть довольным его значением и ощущением, что оно уместно.

physicsmichael 28.05.2010 10:17

Есть ли разница в скорости между [::-1] и reversed()?

Austin Richardson 15.07.2010 01:47

-1, потому что он не скрыт и вы узнаете его достаточно рано, но это полезная функция

Quonux 17.07.2010 02:10

ох, заметил, что [1,2,3,4,5][::-2] тоже работает как положено, что довольно круто

Sam Elliott 24.01.2011 00:28

С его помощью вы можете сделать крутой поисковик палиндрома!

Trufa 14.04.2011 07:03

@Berry list (перевернутый ('бла-бла'))

Tobu 12.01.2012 04:34

@Austin: да, со строками огромная разница: pastebin.com/ZV6cHYhP

Adam Parkin 13.01.2012 00:52

@Trufa: да, очень легко найти палиндром: если someseq == (someseq[::-1]), то это палиндром, и он будет работать с любым типом последовательности (строки, списки и т. д.).

Adam Parkin 13.01.2012 23:36

Неявная конкатенация:

>>> print "Hello " "World"
Hello World

Полезно, если вы хотите уместить длинный текст в несколько строк в скрипте:

hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \
        "Word"

или же

hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " 
         "Word")

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

Rafał Dowgird 19.09.2008 17:48

Ваш пример неверен и вводит в заблуждение. После его запуска часть «Слово» не будет в конце строки приветствия. Он не будет объединяться. Чтобы продолжить на следующей строке, вам потребуется неявное продолжение строки и конкатенация строк, и это произойдет только в том случае, если вы используете какой-либо разделитель, например () или [].

nosklo 20.09.2008 05:26

Неправильно только одно: табуляция перед словом (опечатка). Более того, вы действительно недружелюбны, особенно по отношению к тем, кто даже не нашел времени, чтобы проверить, работает ли это (поскольку вы бы это видели). Вы можете прочитать это: steve.yegge.googlepages.com/bambi-meets-godzilla

e-satis 20.09.2008 22:22

Любой, кто когда-либо забывал запятую в списке строк, знает, насколько зла эта «особенность».

Terhorst 22.09.2008 09:13

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

e-satis 22.09.2008 20:30

Это, наверное, моя любимая функция Python. Вы можете забыть правильный синтаксис, но он останется правильным.

user13876 30.12.2008 12:47

даже лучше: hello = "Greaaaaa Привет \ <представь, что здесь разрыв строки> Мир"

JAB 27.07.2009 23:44

Я всегда пишу + в конце строки (хотя я все еще использую неявное продолжение строки в круглых скобках). Это просто упрощает чтение.

asmeurer 28.12.2010 08:35

Вы можете использовать свойство, чтобы сделать интерфейсы вашего класса более строгими.

class C(object):
    def __init__(self, foo, bar):
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    def _del_foo(self):
        del self._foo

    # any of fget, fset, fdel and doc are optional,
    # so you can make a write-only and/or delete-only property.
    foo = property(fget = _get_foo, fset = _set_foo,
                   fdel = _del_foo, doc = 'Hello, I am foo!')

class D(C):
    def _get_foo(self):
        return self._foo * 2

    def _set_foo(self, value):
        self._foo = value / 2

    foo = property(fget = _get_foo, fset = _set_foo,
                   fdel = C.foo.fdel, doc = C.foo.__doc__)

В Python 2.6 и 3.0:

class C(object):
    def __init__(self, foo, bar):
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    @property
    def foo(self):
        '''Hello, I am foo!'''

        return self._foo

    @foo.setter
    def foo(self, value):
        self._foo = value

    @foo.deleter
    def foo(self):
        del self._foo

class D(C):
    @C.foo.getter
    def foo(self):
        return self._foo * 2

    @foo.setter
    def foo(self, value):
        self._foo = value / 2

Чтобы узнать больше о том, как работает собственность, обратитесь к дескрипторы.

Было бы хорошо, если бы ваши примеры до 2.6 и ваши 2.6 и 3.0 на самом деле представляли одно и то же: имя класса другое, есть комментарии в версии до 2.6, версии 2.6 и 3.0 не содержат кода инициализации.

Confusion 10.01.2010 15:04

Объединение операторов сравнения:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

Если вы думаете, что он делает 1 < x, который получается как True, а затем сравнивает True < 10, который также является True, тогда нет, это действительно не то, что происходит (см. Последний пример). Это действительно переводится в 1 < x and x < 10 и x < 10 and 10 < x * 10 and x*10 < 100, но с меньшим набором текста, и каждый термин оценивается только один раз.

10 > x <= 9 - это не то же самое, что x <= 9 (то есть игнорировать перегруженные операторы)

tzot 22.09.2008 18:40

Конечно. Это был просто пример смешивания разных операторов.

Thomas Wouters 22.09.2008 19:53

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

stalepretzel 17.10.2008 06:23

вам следует добавить несколько примеров, которые также возвращают false. например >>> 10 <x <20 False

ShoeLace 21.11.2008 17:34

Это применимо и к другим операторам сравнения, поэтому люди иногда удивляются, почему код вроде (5 в [5] имеет значение True) имеет значение False (но для начала явно не проверять такие логические значения).

Miles 02.03.2009 21:35

Они действительно должны быть на всех языках, я полностью согласен.

Andrew Szeto 10.07.2009 00:03

В Лиспе нет ничего похожего?

Hai 07.01.2010 00:16

Не то, что я знаю о. Однако в Perl 6 есть такая возможность :)

ephemient 14.01.2010 01:56

Хорошо, но следите за равным приоритетом, например in и =. «A в B == C в D» означает «(A в B) и (B == C) и (C в D)», что может быть неожиданным.

Charles Merriam 10.02.2010 13:28
"каждый термин оценивается только один раз" That's key.
wilhelmtell 13.05.2010 07:56

Азафе: Сравнение Лиспа естественно работает таким образом. Это не особый случай, потому что другого (разумного) способа интерпретировать (< 1 x 10) нет. Вы даже можете применить их к отдельным аргументам, например (= 10): cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/…

Ken 27.05.2010 00:31

@Miles менее запутанным примером может быть «a == b в c», что эквивалентно «a == b и b в c». См. docs.python.org/reference/expressions.html#notin

poolie 22.07.2010 18:56

@Charles Merriam для меня это не неожиданно, просто логично. Хотя использовать A in B == C in D некрасиво.

Joschua 19.12.2010 03:23

Это также отлично подходит для тестов. Вы можете выполнить a == b == c, и он вернет True, только если все три элемента равны.

asmeurer 28.12.2010 08:55

is not и not in тоже на удивление хороши. Очевидно is not - это бинарный оператор 1, а не бинарный, а затем унарный. not in тоже самое. Это делает код вроде 'foo' is not 'bar' более читабельным.

Y.H Wong 24.04.2011 19:12

Кен: Мне нравится версия Python больше, чем версия Lisp, поскольку она позволяет смешивать разные виды сравнений, такие как a <= b <c. Mathematica, которая больше или является диалектом Lisp, действительно позволяет вам использовать разные сравнения - она ​​использует то, что было бы в синтаксисе Lisp (неравенство a '<= b' <c).

Omar Antolín-Camarena 12.01.2012 02:33

Все динамично

«Нет времени компиляции». Все в Python - это среда выполнения. Модуль «определяется» путем выполнения исходного кода модуля сверху вниз, как и сценарий, а результирующее пространство имен является пространством атрибутов модуля. Точно так же класс «определяется» путем выполнения тела класса сверху вниз, а результирующее пространство имен является пространством атрибутов класса. Тело класса может содержать полностью произвольный код, включая операторы импорта, циклы и другие операторы класса. Создать класс, функцию или даже модуль «динамически», как иногда просят, несложно; на самом деле избежать этого невозможно, поскольку все «динамично».

Это дает Python замечательную функцию reload ().

user13876 30.12.2008 12:52

Все динамично ... За исключением классов и модулей, реализованных на C, которые не так динамичны, как все остальное. (попробуйте что-то вроде dict.x = 3, и Python вам не позволит)

Denilson Sá Maia 21.08.2010 00:56

Да, модули и типы, определенные в C, определены во время компиляции, но они по-прежнему созданный во время выполнения. Кроме того, dict.x = 3 не имеет ничего общего с динамикой, но с типом dict, который не позволяет назначать атрибуты. Вы можете создавать свои собственные классы на Python, которые этого не позволяют. Вы можете создать свой собственный тип на языке C, который это позволяет. Это не связано.

Thomas Wouters 10.09.2010 01:33

Как это скрытая функция?

Alexandru 23.01.2011 20:42

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

ncoghlan 01.02.2011 10:22

Повторное поднятие исключений:

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

Оператор Raise без аргументов внутри обработчика ошибок сообщает Python, что нужно повторно вызвать исключение с оригинальной трассировкой нетронутой, позволяя вам сказать: «О, извините, извините, я не хотел это уловить, извините, извините».

Если вы хотите распечатать, сохранить или поиграть с исходной трассировкой, вы можете получить ее с помощью sys.exc_info (), а печать ее, как это сделал бы Python, выполняется с помощью модуля «трассировки».

Извините, но это хорошо известная и общая черта почти для всех языков.

Lucas S. 19.09.2008 18:04

Обратите внимание на текст, выделенный курсивом. Некоторые люди вместо этого будут использовать raise e, который не сохраняет исходную трассировку.

habnabit 27.01.2009 06:14

Возможно, более волшебный, exc_info = sys.exc_info(); raise exc_info[0], exc_info[1], exc_info[2] эквивалентен этому, но вы можете изменить эти значения (например, изменить тип исключения или сообщение)

ianb 06.05.2009 00:27

@Lucas S. Ну, я этого не знал и рад, что здесь написано.

e-satis 23.06.2010 16:32

Возможно, я показываю здесь свою молодость, но я всегда без проблем использовал синтаксис Python 3 в Python 2.7.

wim 14.07.2011 09:49

Синтаксис Python 3 также работает в 2.6 и 2.7, да.

Thomas Wouters 14.07.2011 22:45

Замена значений на месте

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

Правая часть присваивания - это выражение, которое создает новый кортеж. Левая часть присваивания немедленно распаковывает этот (без ссылки) кортеж на имена a и b.

После присвоения новый кортеж не имеет ссылки и помечается для сборки мусора, а значения, привязанные к a и b, меняются местами.

Как отмечено в Раздел учебника Python по структурам данных,

Note that multiple assignment is really just a combination of tuple packing and sequence unpacking.

Использует ли это больше реальной памяти, чем традиционный способ? Я бы предположил, что это так, поскольку вы создаете кортеж, а не только одну переменную подкачки

Nathan 14.06.2010 18:24

Он не использует больше памяти. Он использует меньше ... Я просто написал это в обоих направлениях и декомпилировал байт-код ... компилятор оптимизирует, как вы и надеетесь. Результаты показали, что он настраивает вары, а затем ROT_TWOing. ROT_TWO означает «поменять местами две самые верхние вары стека» ... На самом деле, довольно шикарно.

royal 14.07.2010 02:41

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

asmeurer 28.12.2010 08:12

Я бы предпочел (a, b) = (b, a). Я не думаю, что обязательно ясно, какой приоритет имеет , или =.

Dana the Sane 23.01.2011 22:11

Дана Разумный: присвоение в Python - это оператор, а не выражение, поэтому это выражение было бы недействительным, если бы = имело более высокий приоритет (т.е. оно интерпретировалось как a, (b = b), a).

hbn 24.01.2011 00:27

royal: он действительно создавал кортежи в более старых версиях Python (я думаю, до 2.4).

hbn 24.01.2011 00:27

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

Thiago Chaves 25.05.2011 20:56

Мне нравится эта функция, но мы должны быть осторожны с семантикой обмениваемых объектов. Меня укусили, когда я делал foo[x:y], bar[x:y] = bar[x:y], foo[x:y], когда foo и bar были массивами numpy, потому что нарезка массивов numpy создает представления, а не копии данных!

cberzan 16.02.2012 02:14

Дескрипторы

Они - волшебство целого ряда основных функций Python.

Когда вы используете точечный доступ для поиска члена (например, x.y), Python сначала ищет член в словаре экземпляра. Если он не найден, он ищет его в словаре классов. Если он находит его в словаре классов и объект реализует протокол дескриптора, вместо того, чтобы просто возвращать его, Python выполняет его. Дескриптор - это любой класс, реализующий методы __get__, __set__ или __delete__.

Вот как можно реализовать свою собственную (только для чтения) версию свойства с использованием дескрипторов:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

и вы бы использовали его так же, как встроенное свойство ():

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

Дескрипторы используются в Python, среди прочего, для реализации свойств, связанных методов, статических методов, методов класса и слотов. Их понимание позволяет легко понять, почему многие вещи, которые раньше выглядели как «причуды» Python, являются такими, какие они есть.

У Раймонда Хеттингера есть отличный учебник, который описывает их гораздо лучше, чем я.

Это же дубликат декораторов, не правда ли !? (stackoverflow.com/questions/101268/…)

gecco 20.10.2011 23:18

нет, декораторы и дескрипторы - это совершенно разные вещи, хотя в примере кода я создаю декоратор дескриптора. :)

Nick Johnson 21.10.2011 03:11

Другой способ сделать это - использовать лямбду: foo = property(lambda self: self.__foo).

Pete Peterson 02.11.2011 06:50

@PetePeterson Да, но сам property реализован с помощью дескрипторов, о чем я и писал.

Nick Johnson 02.11.2011 07:40

Доктест: документация и модульное тестирование одновременно.

Пример взят из документации Python:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()

Доктесты - это, конечно, круто, но мне действительно не нравится вся эта чушь, которую нужно набирать, чтобы проверить, должно ли что-то вызывать исключение

TM. 11.03.2009 01:55

Доктесты переоценены и загрязняют документацию. Как часто вы тестируете автономную функцию без setUp ()?

a paid nerd 11.05.2009 08:34

кто сказал, что у вас не может быть настройки в доктесте? напишите функцию, которая генерирует контекст и возвращает locals(), а затем в вашем doctest do locals().update(setUp()) = D

Jiaaro 02.12.2009 20:27

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

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 31.01.2010 03:44

Если автономная функция требует setUp, велики шансы, что ее следует отделить от каких-либо несвязанных вещей или поместить в класс. Затем пространство имен doctest класса можно повторно использовать в doctests метода класса, так что оно немного похоже на setUp, только DRY и читаемое.

Andy Mikhaylenko 17.04.2010 18:38
bemusement.org/diary/2008/October/24/more-doctest-problems - doctests make for ok docs, bad tests
poolie 22.07.2010 19:00

«Как часто вы тестируете автономную функцию» - много. Я считаю, что документы часто возникают естественным образом в процессе проектирования, когда я выбираю фасады.

Gregg Lind 11.02.2011 07:45

Doctest сложно использовать с некоторыми модулями и фреймворками, такими как Django. Обычно использование Doctest затрудняется тем, что какая-то часть дизайна API является тяжелой, чрезмерно связанной с другими компонентами или имеет много зависимостей. Doctest имеет некоторые проблемы и ограничения, но большую часть времени я чувствую, что API, затрудняющее использование Doctest, является более сложным, чем это необходимо.

brandizzi 28.09.2011 22:40

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

vene 12.01.2012 15:22

Я никогда не понимал смысла doctest-ов: если у вас есть фрагмент кода, который проверяет функцию, поместите его в соответствующий модульный тест.

Adam Parkin 18.01.2012 03:49

iter () может принимать вызываемый аргумент

Например:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

Функция iter(callable, until_value) многократно вызывает callable и возвращает результат до тех пор, пока не будет возвращен until_value.

Как новичок в Python, не могли бы вы объяснить, почему здесь необходимо ключевое слово lambda?

SiegeX 13.08.2011 00:29

@SiegeX без лямбда, f.read (1) будет оцениваться (возвращая строку) перед передачей в функцию iter. Вместо этого лямбда создает анонимную функцию и передает ее iter.

jmilloy 31.12.2011 20:43

Слишком ленив, чтобы инициализировать каждое поле в словаре? Без проблем:

В Python> 2.3:

from collections import defaultdict

В Python <= 2.3:

def defaultdict(type_):
    class Dict(dict):
        def __getitem__(self, key):
            return self.setdefault(key, type_())
    return Dict()

В любой версии:

d = defaultdict(list)
for stuff in lots_of_stuff:
     d[stuff.name].append(stuff)

Обновлено:

Спасибо Кен Арнольд. Я повторно реализовал более сложную версию defaultdict. Он должен вести себя точно так же, как тот, что в стандартной библиотеке.

def defaultdict(default_factory, *args, **kw):                              

    class defaultdict(dict):

        def __missing__(self, key):
            if default_factory is None:
                raise KeyError(key)
            return self.setdefault(key, default_factory())

        def __getitem__(self, key):
            try:
                return dict.__getitem__(self, key)
            except KeyError:
                return self.__missing__(key)

    return defaultdict(*args, **kw)

Возможно, вам будет интересно узнать о collections.defaultdict (list).

Thomas Wouters 19.09.2008 21:14

Спасибо. Однако не работает в моей производственной среде. Python 2.3.

pi. 26.01.2009 17:57

Осторожно, повторная реализация defaultdict приводит к вызову type_ при каждом поиске, а не только при отсутствии элемента.

Ken Arnold 14.06.2011 05:33

До python 2.2 вы не могли создать подкласс dict напрямую, поэтому вам нужно было создать подкласс от UserDict.UserDict. Лучше бы еще было обновиться.

SingleNegationElimination 28.07.2011 18:24

Интерпретатор Python

>>> 

Возможно, не менее известная, но, безусловно, одна из моих любимых функций Python.

Причина №1, по которой Python лучше всего остального. </fanboi>

user13876 30.12.2008 12:48

Все остальное вы видели. </smuglispweenie>

Matt Curtis 29.06.2009 17:23

И у него также есть iPython, который намного лучше, чем интерпретатор по умолчанию.

juanjux 11.08.2009 13:51

Хотел бы я использовать iPython как SLIME во всей красе

user130594 21.12.2009 07:22

Первоклассные функции

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

>>> def jim(phrase):
...   return 'Jim says, "%s".' % phrase
>>> def say_something(person, phrase):
...   print person(phrase)

>>> say_something(jim, 'hey guys')
'Jim says, "hey guys".'

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

user13876 30.12.2008 12:49

Любой язык, в котором нет функций первого класса (или, по крайней мере, какой-либо хорошей замены, например указатели функций C), является ошибкой. Обойтись без него совершенно невыносимо.

SingleNegationElimination 17.11.2009 22:06

Это может быть более глупый вопрос, чем я предполагал, но разве это не указатель на функцию? Или я это перепутал?

inspectorG4dget 22.09.2010 08:13

@ InspectorG4dget: это, безусловно, связано с указателями на функции, поскольку может выполнять все те же задачи, но оно немного более общее, более мощное и интуитивно понятное. Особенно мощно, если вы объедините это с тем фактом, что функции могут иметь атрибуты, или тем фактом, что экземпляры определенных классов могут быть вызваны, но это начинает становиться непонятным.

eswald 09.10.2010 21:48

Создание новых типов полностью динамическим способом

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

что в точности совпадает с

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

Наверное, не самое полезное, но это приятно знать.

Редактировать: фиксированное имя нового типа, должно быть NewType, чтобы совпадать с оператором class.

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

Это имеет большой потенциал для полезности, например, JIT ORM.

Mark Cidade 22.09.2008 22:44

Я использую его для создания классов HTML-форм на основе динамического ввода. Очень хорошо!

pi. 18.03.2009 19:00

Я также использовал его для создания динамических форм django (пока не обнаружил наборы форм)

Jiaaro 02.12.2009 20:31

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

spookylukey 01.01.2010 17:02

Чрезвычайно полезно в Django для создания динамических моделей, которые обертывают существующие наборы таблиц схожими структурами.

Josh Smeaton 27.03.2011 07:15

Вы также можете создавать анонимные типы с пустой строкой, например: type ('', (object,), {'x': 'blah'})

bluehavana 17.06.2011 03:49

Может быть очень полезно для инъекций кода.

Avihu Turzion 18.07.2011 12:49

Вы также можете создать экземпляр этого класса в одной строке. x = type("X", (object,), {'val':'Hello'})()

Nick Radford 20.07.2011 00:51

Чередование if и for в понимании списков

>>> [(x, y) for x in range(4) if x % 2 == 1 for y in range(4)]
[(1, 0), (1, 1), (1, 2), (1, 3), (3, 0), (3, 1), (3, 2), (3, 3)]

Я никогда не осознавал этого, пока не изучил Haskell.

способ круто. docs.python.org/tutorial/…

jimmyorr 12.02.2009 02:17

Не так уж и круто, у вас просто понимание списка с двумя циклами for. Что в этом такого удивительного?

Olivier Verdier 14.02.2010 00:10

@Olivier: между двумя циклами for есть if.

Torsten Marek 16.02.2010 14:50

@Torsten: ну, понимание списка уже включает в себя for .. if, так что же такого интересного? Можно написать: [x for i in range(10) if i%2 for j in range(10) if j%2], ничего особо крутого и интересного. Если в середине вашего примера не имеет ничего общего со вторым for.

Olivier Verdier 16.02.2010 20:34

Мне было интересно, есть ли способ сделать это с помощью else? [ a for (a, b) in zip(lista, listb) if a == b else: '-' ]

Austin Richardson 15.07.2010 01:59

в [ _ for _ in _ if _ ] фильтр if для приведенного выше примера должен быть [ _ if _ else _ for _ ].

Dan D. 26.08.2010 18:46

Менеджеры контекста и заявление "with"

Представленный в PEP 343, менеджер контекста - это объект, который действует как контекст времени выполнения для набора операторов.

Поскольку функция использует новые ключевые слова, она вводится постепенно: она доступна в Python 2.5 через директиву __future__. В Python 2.6 и выше (включая Python 3) он доступен по умолчанию.

Я много использовал заявление "с", потому что считаю это очень полезной конструкцией, вот небольшая демонстрация:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

За кулисами здесь происходит то, что заявление "с" вызывает специальные методы __enter__ и __exit__ для файлового объекта. Детали исключения также передаются в __exit__, если какое-либо исключение было вызвано из тела оператора with, что позволяет обрабатывать исключения там.

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

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

Я бы не одобрил обзор кода, который импортировал бы что-либо из будущее. Эти функции скорее милые, чем полезные, и обычно они просто сбивают с толку новичков в Python.

a paid nerd 11.05.2009 08:36

Да, такие «милые» функции, как вложенные области видимости и генераторы, лучше оставить тем, кто знает, что делает. И всем, кто хочет быть совместимым с будущими версиями Python. Для вложенных областей видимости и генераторов «будущие версии» Python означают 2.2 и 2.5 соответственно. Для оператора with «будущие версии» Python означают 2.6.

Chris B. 17.06.2009 22:33

Это может быть само собой разумеющимся, но с python v2.6 + вам больше не нужно импортировать из будущее. with теперь является ключевым словом первого класса.

fitzgeraldsteele 23.11.2009 17:28

В 2.7 может быть несколько withs :) with open('filea') as filea and open('fileb') as fileb: ...

Austin Richardson 15.07.2010 01:50

@Austin, я не мог заставить этот синтаксис работать на 2.7. это, однако, сработало: with open('filea') as filea, open('fileb') as fileb: ...

wim 14.07.2011 09:29

Было бы полезно объяснить, почему и в каких случаях этот оператор with отличается от f = open('foo.txt', 'w').

gb. 03.11.2011 06:29

Некоторые из фаворитов встроенный, map (), reduce () и filter (). Все очень быстро и мощно.

Будьте осторожны с reduce (). Если вы не будете осторожны, вы можете писать очень медленные сокращения.

S.Lott 27.09.2008 04:49

И будьте осторожны с map (), она устарела в версии 2.6 и удалена в версии 3.0.

user13876 30.12.2008 12:51

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

recursive 01.01.2009 12:28

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

juanjux 11.08.2009 13:57

@sil: map все еще существует в Python 3, как и filter, и reduce существует как functools.reduce.

u0b34a0f6ae 04.10.2009 05:17

@recursive: я не хочу, чтобы вы создали выражение понимания / генератора списка, которое выполняет действие reduce()

SingleNegationElimination 17.11.2009 22:08

Правильное утверждение: «reduce() может достичь всего, что вы можете делать с map(), filter() или списком понимания».

Kragen Javier Sitaker 12.01.2012 08:31

Распаковка аргументов функции

Вы можете распаковать список или словарь в качестве аргументов функции, используя * и **.

Например:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Очень полезный ярлык, поскольку списки, кортежи и словари широко используются в качестве контейнеров.

Используй это все время, люби это.

Skurmedel 23.06.2010 12:48

* также известен как оператор splat

Gabriel 15.07.2010 11:03

Мне нравится эта функция, но, к сожалению, pylint нет.

Stephen Paulger 25.03.2011 17:46

Совет Пилинта - это не закон. Другой способ - apply (callable, arg_seq, arg_map) - устарел, начиная с 2.3.

Yann Vernier 04.05.2011 15:50

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

Andrew 21.11.2011 23:40

Однажды я видел, как это использовалось в коде, и подумал, что он делает. К сожалению, поиск в Google "Python **" затруднен.

Fraser Graham 14.01.2012 03:33

Это называется оператором splat. Таким образом, вы можете найти в Google "python splat", но вряд ли кто-то узнает имя, если он не знает эту функцию :-p

e-satis 14.01.2012 15:46

@andrew: Pylint имеет тенденцию жаловаться на множество классических идиом, таких как try / except ImportError

e-satis 14.01.2012 15:52

@ e-satis: это потому, что многие из этих «классических идиом» - плохая практика. Я согласен с тем, что Pylint может быть излишне «придирчивым», но в подавляющем большинстве случаев, если у вас нет явной причины не придерживаться его рекомендаций, лучше всего подчиниться (а в случаях, когда у вас есть веская причина, вы всегда можете сделать pylint-disable для подавления предупреждения в конкретном случае)

Adam Parkin 18.01.2012 03:44

@ Адам: не поймите меня неправильно, у меня на самом деле запускается pylint каждый раз, когда мой документ сохраняется автоматически. но ошибка Try / except действительно полезна. Понимание словаря тоже, а pylint их не понимает. Pylint обычно много жалуется в модульном тестировании, если вы устанавливаете переменные без их использования, потому что на самом деле этого требует тест. Важно не впадать в психику с предупреждениями о pylint, иначе вы просто перестанете кодировать. И использование * или ** на самом деле является чистым кодом, а не грязным.

e-satis 18.01.2012 15:32

Странно, у меня никогда не было Pylint жаловаться на понимание слов, и я использую их все время. Большинство предупреждений модульного теста связано с тем, что модуль unittest не совместим с PEP-8 (например: принудительно присвоить методу настройки имя «setUp» вместо «set_up»). Но да, я согласен, что Пилинт может быть (скажем так) временами чрезмерно усердным. Что я делаю, так это каждый раз, когда я добавляю директиву disable-pylint, я сопровождаю ее комментарием, оправдывающим ее использование. Я считаю, что это хорошо работает, и несколько раз моя команда бросала мне вызов, и в конце концов я нашел лучший способ что-то сделать.

Adam Parkin 19.01.2012 20:18

Если pylint жалуется на понимание dict, значит, он работает под управлением python 2.6 (версия, встроенная в vim). Чтобы исправить это, запустите pylint с помощью 2.7 (что для меня в OSX означало, что мне пришлось самому скомпилировать macvim tartley.com/?p=1355, но на других платформах я Думаю, существуют бинарные файлы vim с поддержкой 2.7. Для этого вам нужно установить 2.7, macvim его использует.

Jonathan Hartley 11.02.2012 14:54

Да, предупреждение pylint о "** magic" глупо и может быть отключено глобально.

Jonathan Hartley 11.02.2012 14:56

В словарях есть метод get ()

В словарях есть метод get (). Если вы сделаете d ['key'], а ключа там нет, вы получите исключение. Если вы сделаете d.get ('key'), вы вернетесь None, если 'key' там нет. Вы можете добавить второй аргумент, чтобы вернуть этот элемент вместо None, например: d.get ('key', 0).

Он отлично подходит для таких вещей, как сложение чисел:

sum[value] = sum.get(value, 0) + 1

также проверьте метод setdefault.

Daren Thomas 13.10.2008 21:29

также класс checkout collections.defaultdict.

jfs 23.11.2008 13:35

Если вы используете Python 2.7 или новее, или 3.1 или новее, проверьте класс Counter в модуле коллекций. docs.python.org/library/collections.html#collections.Counter

Elias Zamaria 12.10.2010 05:33

Ой, все это время я занимался get(key, None). Не имел понятия, что None предоставляется по умолчанию.

Jordan Reiter 19.10.2011 20:41

Если вы используете exec в функции, правила поиска переменных кардинально меняются. Замыкания больше невозможны, но Python допускает произвольные идентификаторы в функции. Это дает вам "изменяемые locals ()" и может использоваться для импорта идентификаторов звездочкой. С другой стороны, это замедляет каждый поиск, потому что переменные попадают в dict, а не в слоты во фрейме:

>>> def f():
...  exec "a = 42"
...  return a
... 
>>> def g():
...  a = 42
...  return a
... 
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_CONST               1 ('a = 42')
              3 LOAD_CONST               0 (None)
              6 DUP_TOP             
              7 EXEC_STMT           

  3           8 LOAD_NAME                0 (a)
             11 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_CONST               1 (42)
              3 STORE_FAST               0 (a)

  3           6 LOAD_FAST                0 (a)
              9 RETURN_VALUE        

Просто для придирки: это относится только к голому exec. Если вы укажете пространство имен для использования, например, "d = {}; exec" a = 42 "in d", этого не произойдет.

Brian 22.09.2008 02:48

Начиная с версии 2.5 в dicts есть специальный метод __missing__, который вызывается для недостающих элементов:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

В collections также есть подкласс dict, называемый defaultdict, который делает почти то же самое, но вызывает функцию без аргументов для несуществующих элементов:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Я рекомендую преобразовывать такие диктовки в обычные, прежде чем передавать их функциям, которые не ожидают таких подклассов. Многие коды используют d[a_key] и перехватывают KeyErrors, чтобы проверить, существует ли элемент, который добавит новый элемент в dict.

Сюда я кладу вилочные бомбы.

Vince 04.09.2009 00:37

Я предпочитаю использовать setdefault. m = {}; m.setdefault ('фу', 1)

grayger 03.12.2009 06:03

@grayger имел в виду именно m = {}; m.setdefault('foo', []).append(1).

Cristian Ciupitu 28.05.2010 22:53

Однако есть случаи, когда передача defaultdict очень удобна. Функция может, например, перебирать значение, и она работает для неопределенных ключей без дополнительного кода, поскольку по умолчанию это пустой список.

Marian 29.05.2010 06:22

defaultdict в некоторых случаях лучше, чем setdefault, поскольку он не создает объект по умолчанию пока не, ключ отсутствует. setdefault создает его независимо от того, отсутствует он или нет. Если ваш объект по умолчанию требует больших затрат на создание, это может снизить производительность - я получил приличное ускорение одной программы, просто изменив все вызовы setdefault.

Whatang 12.02.2011 20:56

defaultdict также более мощный, чем метод setdefault в других случаях. Например, для счетчика - dd = collections.defaultdict(int) ... dd[k] += 1 против d.setdefault(k, 0) += 1.

Mike Graham 11.04.2011 01:56

Если вы используете дескрипторы в своих классах, Python полностью обходит __dict__ для этого ключа, что делает его удобным местом для хранения таких значений:

>>> class User(object):
...  def _get_username(self):
...   return self.__dict__['username']
...  def _set_username(self, value):
...   print 'username set'
...   self.__dict__['username'] = value
...  username = property(_get_username, _set_username)
...  del _get_username, _set_username
... 
>>> u = User()
>>> u.username = "foo"
username set
>>> u.__dict__
{'username': 'foo'}

Это помогает поддерживать dir() в чистоте.

Если вам не нравится использовать пробелы для обозначения областей действия, вы можете использовать стиль C {}, выполнив:

from __future__ import braces

Это зло. :)

Jason Baker 22.09.2008 08:32

>>> from __future__ импортировать фигурные скобки Файл "<stdin>", строка 1 SyntaxError: не шанс: P

Benjamin W. Smith 22.09.2008 23:55

Подождите, а разве будущий пакет не является будущим дополнением к языку? Планируют ли они когда-нибудь добавить фигурные скобки?

James McMahon 16.10.2008 15:50

Динамические пробелы - половина достоинств Python. Это ... искажено.

stalepretzel 17.10.2008 06:28

это кощунство!

Berk D. Demir 22.03.2009 16:24

Я думаю, что здесь может быть синтаксическая ошибка, не должна ли она быть "из фигурных скобок импорта __прошлый__"?

Bill K 30.04.2009 01:26

из __cruft__ импортировать фигурные скобки

Phillip B Oldham 18.06.2009 11:16

Признаюсь, это забавно, но, наоборот, что насчет слепых? Я помню, как некоторое время назад читал человека, который был слеп и разочарован тем, что он / она не может использовать Python из-за отсутствия скобок для утверждений.

David 22.06.2009 23:32

Я могу понять использование фигурных скобок для минификации кода :)

Jiaaro 25.06.2009 20:35

Полностью нарушает идиому Python

Joshua Partogi 22.07.2009 06:16

@ Дэвид: Чем брекеты лучше для слепых? В лучшем случае (код с хорошим отступом, который обеспечивает Python) фигурные скобки добавят лишь крохотной ясности. На мой взгляд, гораздо легче заметить блок текста с пробелами раньше, чем наличие небольшого типографского символа. Разборчивость фигурных скобок зависит от того, в какую версию OTBS верит этот человек. Встроенные фигурные скобки, которые я предпочитаю, было бы ужасно читать без надлежащего зрения.

3Doubloons 27.07.2009 00:31

@Alex: Как читатель текста определяет уровень отступа? Вам понадобится программа для чтения текста Python, которая сообщит вам: «для <stuff> двоеточие, переход новой строки, переходите новую строку <следующий оператор>». Теперь добавьте несколько отступов: «indent indent indent для <stuff> двоеточие newline indent indent indent indent pass newline indent indent indent <следующий оператор>»

jmucchiello 02.09.2009 09:47

jmucchiello: Да, вам нужно что-то специфичное для Python. Программа чтения с экрана должна произносить токены, которые использует интерпретатор Python, «намерение в», «отступ».

u0b34a0f6ae 15.09.2009 02:40

@David, @jmucchiello: есть скрипт, который добавляет фигурные скобки к каждому блоку в комментарии (# }), и на самом деле я читал о слепых людях, которые используют его, чтобы позволить им писать Python :)

Esteban Küber 21.10.2009 22:40

@David, @jmucchiello: Ах, вы имели в виду слепых, а не просто «ужасно плохое зрение» - слепых.

3Doubloons 26.11.2009 10:01

Я знаю нескольких разработчиков, изучающих Python (но знающих язык стиля c), которым это понравится. Просто потому, что они ничего не знают;)

Justin 28.05.2010 19:28

Слепой программист может использовать этот синтаксис: python.org/doc/humor/…

Joschua 29.12.2010 15:42

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

Adam Fraser 25.05.2011 16:45

Мне сняли брекеты, когда я выросла!

Chris Johnson 14.07.2011 00:54

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

Sebastian Noack 15.08.2011 19:22

Это чертовски пасхальное яйцо. Я люблю сообщества oss ...

AndreasT 17.08.2011 15:58

__slots__ - хороший способ сэкономить память, но очень сложно определить значения объекта. Представьте себе следующий объект:

class Point(object):
    __slots__ = ('x', 'y')

Теперь у этого объекта, очевидно, есть два атрибута. Теперь мы можем создать его экземпляр и построить его следующим образом:

>>> p = Point()
>>> p.x = 3
>>> p.y = 5
>>> dict((k, getattr(p, k)) for k in p.__slots__)
{'y': 5, 'x': 3}

Однако это не сработает, если точка была разделена на подклассы и были добавлены новые слоты. Однако Python автоматически реализует __reduce_ex__, чтобы помочь модулю copy. Этим можно злоупотребить, чтобы получить диктат ценностей:

>>> p.__reduce_ex__(2)[2][1]
{'y': 5, 'x': 3}

Ого, мне это может пригодиться!

user13876 30.12.2008 12:46

Помните, что __reduce_ex__ можно переопределить в подклассах, и, поскольку он также используется для травления, это часто бывает. (Если вы создаете контейнеры данных, вам следует подумать об их использовании! Или это младшие братья и сестры __getstate__ и __setstate__.)

Ken Arnold 01.07.2010 00:53

Тогда вы все еще можете использовать object.__reduce_ex__(p, 2)[2][1].

Armin Ronacher 01.07.2010 03:13

Расширенная операция нарезки Python имеет малоизвестный элемент синтаксиса - многоточие:

>>> class C(object):
...  def __getitem__(self, item):
...   return item
... 
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)

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

см. stackoverflow.com/questions/118370/… для получения дополнительной информации

molasses 23.09.2008 04:33

На самом деле многоточие весьма полезно при работе с многомерными массивами из модуля numpy.

Denilson Sá Maia 21.08.2010 00:33

Предполагается, что это будет более полезно в Python 3, где многоточие станет буквальным. (Попробуйте, вы можете ввести ... в интерпретаторе Python 3, и он вернет Eillipsis)

asmeurer 28.12.2010 08:21

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

>>> class C(object):
...  id = id
... 
>>> C().id()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: id() takes exactly one argument (0 given)

Однако вы можете создать небольшой дескриптор привязки, который сделает это возможным:

>>> from types import MethodType
>>> class bind(object):
...  def __init__(self, callable):
...   self.callable = callable
...  def __get__(self, obj, type=None):
...   if obj is None:
...    return self
...   return MethodType(self.callable, obj, type)
... 
>>> class C(object):
...  id = bind(id)
... 
>>> C().id()
7414064

Проще и проще сделать это как свойство, в данном случае: class C (object): id = property (id)

Pi Delport 03.10.2010 02:56

лямбда также является хорошей альтернативой: class C(object): id = lambda s, *a, **kw: id(*a, **kw); и лучшая версия привязки: def bind(callable): return lambda s, *a, **kw: callable(*a, **kw)

Lie Ryan 31.10.2010 02:40

Именованное форматирование

% -форматирование требует словаря (также применяется проверка% i /% s и т. д.).

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

А поскольку locals () также является словарем, вы можете просто передать его как dict и получить% -подстановки из ваших локальных переменных. Я думаю, что это не одобряется, но все упрощает ...

Форматирование нового стиля

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))

Будет прекращено и в конечном итоге заменено методом строки format ().

Constantin 05.10.2008 13:41

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

pixelbeat 13.10.2008 02:45

По-видимому, работает в python 3.0.1 (необходимо добавить круглые скобки вокруг вызова печати).

Pasi Savolainen 01.07.2009 15:32

а хэш, а? Я вижу, откуда ты.

shylent 14.11.2009 16:45

% -форматирование не исчезнет в ближайшее время, но метод "форматирования" строк - это новый (текущий) метод передового опыта. Он поддерживает все, что делает% -форматирование, и большинство людей думают, что API и синтаксис форматирования намного лучше. (Я включен.) В Python есть третий метод, string.Template, добавленный в версии 2.4; в основном это никому не нравится.

Larry Hastings 01.01.2010 04:51

Форматирование% s не будет прекращено. str.format (), безусловно, более питоничен, но на самом деле в 10 раз медленнее для простой замены строки. Я считаю, что форматирование% s по-прежнему является лучшей практикой.

Kenneth Reitz 14.07.2010 16:34

Для полноты картины locals()-эквивалентом для форматирования нового стиля, конечно же, является print "The {foo} is {bar}".format(**locals()).

Ben Blank 19.01.2011 21:57

Мне нравится locals (), но у него есть неприятный побочный эффект: если вы используете pylint, вы часто будете получать ошибки из-за того, что не используете переменную в области видимости функции.

hughdbrown 23.01.2011 20:17

В Python 3.2 эквивалентом locals() является print("The {foo} is {bar}".format_map(locals())).

ncoghlan 01.02.2011 09:07

Этот формат медленнее, его можно исправить. В конце концов, он делает то же самое, что и% форматирование. И в 3.1.3 time он дает мне следующие измерения скорости: >>> timeit('''"a %(b)s" % {"b": "c"}''') 0.2503829002380371 >>> timeit('''"a {b}".format(b = "c")''') 0.41667699813842773

Arne Babenhauserheide 11.01.2012 14:13

Эй, @matt, непонятно, против какого формата вы рекомендуете, и особенно неясно, почему.

Jonathan Hartley 11.02.2012 15:10

Будьте осторожны с изменяемыми аргументами по умолчанию

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Вместо этого вы должны использовать значение дозорного, обозначающее «не задано», и заменить его изменяемым значением по умолчанию:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

Это определенно одна из самых неприятных скрытых функций. Время от времени я сталкивался с этим.

Torsten Marek 23.09.2008 21:42

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

Robert Rossney 05.11.2009 23:43

Не могли бы вы подробно объяснить, как это происходит?

grayger 03.12.2009 06:25

@grayger: при выполнении оператора def его аргументы оцениваются интерпретатором. Это создает (или повторно связывает) имя с объектом кода (набором функции). Однако аргументы по умолчанию создаются как объекты во время определения. Это верно для любого времени объекта по умолчанию, но важно только (демонстрируя видимую семантику), когда объект является изменяемым. Невозможно повторно привязать это имя аргумента по умолчанию в закрытии функции, хотя оно, очевидно, может быть переопределено для любого вызова или вся функция может быть переопределена).

Jim Dennis 24.06.2010 08:20

@Robert, конечно, кортеж аргументов может быть неизменным, но объекты, на которые он указывает, не обязательно неизменяемы.

poolie 22.07.2010 18:59

Один быстрый прием, который сделает вашу инициализацию немного короче: x = x или []. Вы можете использовать это вместо 2-строчного оператора if.

dave mankoff 27.08.2010 06:58

Значения по умолчанию также становятся неприятными, если вы используете более одного из них. Например, вы написали такую ​​функцию, как: <function> def f (a = [], b = [], c = []): a.append (3) </ function>. Вы случайно изменили значения a, b и c, не прикасаясь к ним. Это потому, что похожие значения по умолчанию, похоже, указывают на одно и то же в памяти. Возникают неприятные ошибки

inspectorG4dget 22.09.2010 08:44

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

flow 17.10.2010 23:39

Это похоже на ошибку в компиляторе, не так ли?

Leo 22.12.2011 01:23

Просто замечание, что pylint сильно жалуется на такое использование, как и должно.

Peter V 12.01.2012 04:42

@davemankoff: Я считаю, что это плохая привычка, потому что рано или поздно вы по ошибке отклоните действительное ложное значение.

Ori 12.01.2012 07:26

Это был буквально вопрос собеседования для моей нынешней работы. :) Это, наверное, классический Python то.

Adam Parkin 13.01.2012 01:01

Распаковка кортежа:

>>> (a, (b, c), d) = [(1, 2), (3, 4), (5, 6)]
>>> a
(1, 2)
>>> b
3
>>> c, d
(4, (5, 6))

Более того, вы можете сделать это в аргументах функции (в Python 2.x; Python 3.x больше этого не допускает):

>>> def addpoints((x1, y1), (x2, y2)):
...     return (x1+x2, y1+y2)
>>> addpoints((5, 0), (3, 5))
(8, 5)

Как бы то ни было, распаковка кортежей в определениях функций прекращается в python 3.0.

Ryan 29.09.2008 05:18

В основном потому, что, насколько я понимаю, это делает реализацию действительно неприятной. (Например, в inspect.getargs в стандартной библиотеке - нормальный путь (без аргументов кортежа) составляет около 10 строк, и есть около 30 дополнительных строк для обработки аргументов кортежа (которые используются только изредка).) Мне все же грустно.

babbageclunk 25.11.2008 17:17

Похоже, в версии 3.0: / вынимают часть батареек.

FeatureCreep 01.01.2010 23:59

Хорошо, что они его удалили, потому что это некрасиво, и вы можете просто имитировать это, набрав: x1, x2 = x; y1, y2 = y (если у вас есть аргументы x, y)

Joschua 11.03.2010 19:49

Это позор. Я надеялся, что для остальных аргументов будет добавлена ​​поддержка *, чтобы вы могли делать такие вещи, как a, b, * c = [1, 2, 3, 4, 5] (эквивалентно a = 1, b = 2, c = [3, 4, 5]).

hbn 24.01.2011 00:40

@yangyang: добавлен был. Единственное, что было удалено, - это распаковка кортежей в определениях функций. Вместо этого вы просто переносите такую ​​распаковку в первую строку реализации функции.

ncoghlan 01.02.2011 10:07

разархивировать ненужное в Python

Кто-то написал в блоге о том, что Python не имеет функции распаковки для zip (). unzip легко вычислить, потому что:

>>> t1 = (0,1,2,3)
>>> t2 = (7,6,5,4)
>>> [t1,t2] == zip(*zip(t1,t2))
True

Поразмыслив, я бы предпочел явную unzip ().

def unzip (x): return zip (* x) Готово!

bukzor 27.06.2010 21:07

Решение немного тонкое (я могу понять точку зрения любого, кто его спросит), но я также могу понять, почему это было бы лишним

inspectorG4dget 22.09.2010 08:47

+1. Я собирался добавить это, но, похоже, меня это опередило.

asmeurer 28.12.2010 08:57

Чтобы добавить больше модулей Python (особенно сторонних), большинство людей, похоже, используют переменные среды PYTHONPATH или добавляют символические ссылки или каталоги в свои каталоги пакетов сайтов. Другой способ - использовать файлы * .pth. Вот официальное объяснение документа Python:

"The most convenient way [to modify python's search path] is to add a path configuration file to a directory that's already on Python's path, usually to the .../site-packages/ directory. Path configuration files have an extension of .pth, and each line must contain a single path that will be appended to sys.path. (Because the new paths are appended to sys.path, modules in the added directories will not override standard modules. This means you can't use this mechanism for installing fixed versions of standard modules.)"

Я никогда не устанавливал связи между этим файлом .pth в каталоге site-packages из setuptools и этой идеей. классно.

dave paola 14.07.2010 06:07

Исключение еще предложение:

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

Использование предложения else лучше, чем добавление дополнительного кода в предложение try, поскольку оно позволяет избежать случайного перехвата исключения, которое не было вызвано кодом, защищаемым оператором try ... except.

См. http://docs.python.org/tut/node10.html

+1 это круто. Если блок try выполняется без ввода каких-либо блоков исключений, то вводится блок else. И, конечно же, выполняется блок finally.

inspectorG4dget 22.09.2010 08:49

Наконец-то я понимаю, почему здесь «еще»! Спасибо.

taynaron 07.12.2010 21:26

Было бы разумнее использовать continue, но я думаю, он уже занят;)

Paweł Prażak 16.12.2010 20:58

Обратите внимание, что в более старых версиях Python2 у вас не может быть обоих предложений else: и finally: для одного и того же блока try:

Kevin Horn 27.05.2011 02:49

@ Paweł Praak: Я не думаю, что это так. Поскольку continue и break относятся к циклам, и это единственный условный оператор.

Isaac Nequittepas 20.09.2011 18:42

@IsaacRemuant, вы правы. Может быть, что-то вроде ожидаемого или дефолта, или действия, или нормального? :)

Paweł Prażak 27.09.2011 12:17

@ Paweł Praak, как упомянул Кевин Хорн, этот синтаксис был введен после первоначального выпуска Python, и добавление новых зарезервированных ключевых слов к существующему языку всегда проблематично. Вот почему существующее ключевое слово обычно используется повторно (например, «auto» в недавнем стандарте C++).

Constantin 07.10.2011 14:28

Синтаксис for ... else (см. http://docs.python.org/ref/for.html)

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

Блок «else» обычно выполняется в конце цикла for, если не вызывается break.

Приведенный выше код можно эмулировать следующим образом:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")

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

codeape 10.10.2008 10:44

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

sundar - Remember Monica 13.10.2008 12:34

ах. Никогда не видел этого! Но я должен сказать, что это неправильно. Кто мог ожидать, что блок else будет выполняться только в том случае, если break никогда не выполняется? Я согласен с codeape: похоже, что else введено для пустого foos.

Daren Thomas 13.10.2008 21:31

Я добавил эквивалентный код, не использующий else.

jfs 23.11.2008 13:32

Я считаю это гораздо менее полезным, чем выполнение предложения else, если бы не выполнялся цикл for. Я так много раз хотел этого, но никогда не находил случая, когда бы мне хотелось это использовать.

Draemon 27.11.2008 07:09

Кто-нибудь помнит FOR var… NEXT var… END FOR var в Sinclair QL SuperBasic? Все, что находится между NEXT и END FOR, будет выполняться в конце цикла, если только не был выдан EXIT FOR. Синтаксис Который стал чище :)

tzot 15.01.2009 15:28

похоже, что ключевое слово должно быть наконец, а не иначе

Jiaaro 25.06.2009 20:31

За исключением того, что finally уже используется таким образом, чтобы этот набор всегда выполнялся.

Roger Pate 28.06.2009 02:34

Это действительно удобно, и я им пользуюсь, но каждый раз требует поясняющего комментария.

u0b34a0f6ae 15.09.2009 02:38

Определенно не должно быть «else». Может быть, «then» или что-то в этом роде, а затем «else», когда цикл никогда не выполнялся.

Tor Valamo 10.01.2010 19:26

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

man1 14.07.2010 03:20

Эй, люди забыли упомянуть, что эта идиома также работает для петель while.

Denilson Sá Maia 21.08.2010 00:24

Я всегда думал, что конструкция for...then...else была бы лучше, где then выполняется только в случае успеха for, else, когда невозможно ввести for (например: for i in []; pass; else; print "empty list". Но тогда я новичок. :)

Phillip B Oldham 21.08.2010 04:32

Работает ли это ТОЛЬКО, если в цикле for есть оператор break или есть другие обстоятельства, при которых этот трюк работает таким образом?

inspectorG4dget 22.09.2010 08:52

@ InspectorG4dget: отлично работает без перерыва ... но бесполезно, если нет перерыва. (Код в else может быть просто вытеснен на один уровень)

jkerian 22.09.2010 10:04

@jkerian: Большое спасибо. Я наблюдал за этим поведением, но меня интересовало, что такое «будет ли это работать так же, если бы вместо break использовалось return?»

inspectorG4dget 22.09.2010 10:10

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

flow 17.10.2010 23:37

Да, использование этого синтаксиса заставило меня закричать парочка программистов на PHP и C. Иди разберись. :-)

terminus 21.11.2010 15:32

Никогда не используйте for-else. Он не делает того, что думает следующий программист, который увидит ваш код.

inanutshellus 22.04.2011 17:08

Раньше меня тоже сбивало с толку это поведение, пока я не подумал о нем с точки зрения try.. except.. else... Поведение Python for.. else.. согласуется с тем, как выполняются блоки try. Если содержимое try или for удачно, перейдите к else.

ryanshow 12.01.2012 05:31

Операторы, изменяющие поток управления (например, break), обычно являются плохим выбором для начала, объедините это с необычным использованием ключевого слова (в данном случае "else"), и вы получите код, который еще труднее читать, особенно для новичков. Я бы определенно уклонился от этого.

Adam Parkin 13.01.2012 23:31

if any(i == 0 for i in foo): ... Я бы выбрал формулировку для такого кода. Может быть, это мое влияние на Haskell.

Theo Belaire 16.01.2012 00:18

Многие люди не знают о функции "dir". Это отличный способ выяснить, что объект может делать из интерпретатора. Например, если вы хотите увидеть список всех строковых методов:

>>> dir("foo")
['__add__', '__class__', '__contains__', (snipped a bunch), 'title',
 'translate', 'upper', 'zfill']

А затем, если вам нужна дополнительная информация о конкретном методе, вы можете вызвать по нему «помощь».

>>> help("foo".upper)
    Help on built-in function upper:

upper(...)
    S.upper() -> string

    Return a copy of the string S converted to uppercase.

dir () необходим для разработки. Для больших модулей я улучшил его, добавив фильтрацию. См. pixelbeat.org/scripts/inpy

pixelbeat 13.10.2008 02:46

Вы также можете напрямую использовать help: help ('foo')

yuriks 26.12.2008 21:44

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

akaihola 10.01.2009 06:50

см .: Альтернатива Python dir (). Легко печатать; легко читать! Только для людей: github.com/inky/see

compie 22.07.2010 22:26

Я называю это справочные страницы python, и их также можно реализовать для работы, когда вызывается man, а не help.

inspectorG4dget 22.09.2010 08:53

@compie - see () очень удобен. Очень хорошо! Намного легче читать, чем вывод dir ()

Adam Parkin 19.01.2012 20:41

Access Dictionary elements as attributes (properties). so if an a1=AttrDict() has key 'name' -> instead of a1['name'] we can easily access name attribute of a1 using -> a1.name


class AttrDict(dict):

    def __getattr__(self, name):
        if name in self:
            return self[name]
        raise AttributeError('%s not found' % name)

    def __setattr__(self, name, value):
        self[name] = value

    def __delattr__(self, name):
        del self[name]

person = AttrDict({'name': 'John Doe', 'age': 66})
print person['name']
print person.name

person.name = 'Frodo G'
print person.name

del person.age

print person

нет названия или объяснения? где здесь скрытая особенность?

Sanjay Manohar 08.09.2010 08:15

Функция сортировки Python правильно сортирует кортежи (т. Е. Используя знакомый лексикографический порядок):

a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]
print sorted(a)
#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]

Полезно, если вы хотите отсортировать список людей по возрасту, а затем по имени.

Это следствие корректной работы сравнения кортежей, т.е. (1, 2) <(1, 3).

Constantin 05.10.2008 13:43

Это полезно для кортежей версий: (1, 9) <(1, 10).

Roger Pate 28.06.2009 03:00

Условное присвоение

x = 3 if (y == 1) else 2

Он делает именно то, что звучит: «присвоить 3 переменной x, если y равно 1, в противном случае присвоить 2 переменной x». Обратите внимание, что скобки не обязательны, но мне они нравятся для удобства чтения. Вы также можете связать его, если у вас есть что-то более сложное:

x = 3 if (y == 1) else 2 if (y == -1) else 1

Хотя в какой-то момент это заходит слишком далеко.

Обратите внимание, что вы можете использовать if ... else в любом выражении. Например:

(func1 if y == 1 else func2)(arg1, arg2) 

Здесь будет вызываться func1, если y равно 1, и func2 в противном случае. В обоих случаях соответствующая функция будет вызываться с аргументами arg1 и arg2.

Аналогично верно и следующее:

x = (class1 if y == 1 else class2)(arg1, arg2)

где class1 и class2 - два класса.

Задание - это не особая часть. Вы можете так же легко сделать что-то вроде: return 3 if (y == 1) else 2.

Brian 09.11.2008 08:39

Другой способ сделать это: y == 1 и 3 или 2

yuriks 26.12.2008 21:46

Этот альтернативный путь чреват проблемами. Во-первых, обычно это работает: if y == 1: # 3 else if y == 70: # 2 Почему? y == 1 оценивается только, ТО y == 70, если y == 1 ложно. В этом операторе: y == 1 и 3 или 2 - 3 и 2 оцениваются так же, как y == 1.

kylebrooks 24.01.2009 00:45

Этот альтернативный способ - первый раз, когда я увидел запутанный Python.

Craig McQueen 09.06.2009 08:18

Кайлбрукс: В этом случае логические операторы не замыкаются. Он будет оценивать только 2, если bool (3) == False.

RoadieRich 12.07.2009 04:23

это кодирование в обратном стиле сбивает меня с толку. что-то вроде x = ((y == 1) ? 3 : 2) имеет для меня больше смысла

mpen 20.10.2009 11:12

Я чувствую полную противоположность @Mark, тернарные операторы в стиле C всегда сбивали меня с толку, правая сторона или середина оцениваются при ложном условии? Я предпочитаю тернарный синтаксис Python.

Jeffrey Harris 03.12.2009 19:51

@Mark "x = (y == 1) and 3 or 2" также действителен.

Kyle Ambroff 01.03.2010 03:13

Я думаю, что тернарные операторы в стиле C проще, больше похожи на английский: 'am I drunk' ? 'yes, make out with her' : 'no, dont even think about it'

adamJLev 06.05.2010 23:43

x = 3 if (y == 1) else 2 - Я считаю, что во многих случаях x = (2, 3)[y==1] на самом деле более читабелен (обычно с очень длинными операторами, поэтому вы можете сохранить результаты (2, 3) вместе).

Ponkadoodle 16.05.2010 10:50

Каким-то образом Гвидо и ребятам из Python удалось сделать одну из наиболее искаженных частей языка C удобочитаемой и легко понятной, даже если вы не знаете, что это такое.

asmeurer 28.12.2010 08:16

@Infinity, вам следует проконсультироваться с врачом, чтобы заменить постоянную постоянную "я пьян" недетерминированной функцией am_i_drunk ().

j0057 12.01.2012 03:29

Когда я впервые увидел тройную операцию в Python, мне показалось, что ее трудно читать, в основном из-за моего знакомства с оператором в стиле C. Не уверен, какой из них лучше («трава мокрая, если идет дождь, иначе трава сухая» или «если идет дождь, то трава мокрая, иначе трава сухая»)

Adam Parkin 13.01.2012 01:27
  • Подчеркивание, оно содержит самое последнее выходное значение, отображаемое интерпретатором (в интерактивном сеансе):
>>> (a for a in xrange(10000))
<generator object at 0x81a8fcc>
>>> b = 'blah'
>>> _
<generator object at 0x81a8fcc>
  • Удобный контроллер веб-браузера:
>>> import webbrowser
>>> webbrowser.open_new_tab('http://www.stackoverflow.com')
  • Встроенный http-сервер. Для обслуживания файлов в текущем каталоге:
python -m SimpleHTTPServer 8000
  • AtExit
>>> import atexit

Почему не просто SimpleHTTPServer?

Andrew Szeto 10.07.2009 00:17

Стоит отметить, что _ доступен только в интерактивном режиме. при запуске скриптов из файла _ не имеет особого значения.

SingleNegationElimination 17.11.2009 21:52

@TokenMacGuy: Фактически, вы можете определить _ как переменную в файле (на всякий случай, если вы делать захотите использовать запутанный Python).

asmeurer 28.12.2010 08:24

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

wim 19.07.2011 15:22

@asmeurer Я часто использую _ как имя для переменных, которые меня не интересуют (например, for _, desired_value, _ in my_tuple_with_some_irrelevant_values). Да, как прологер :)

brandizzi 28.09.2011 22:51

__getattr __ ()

getattr - действительно хороший способ создания универсальных классов, что особенно полезно, если вы пишете API. Например, в FogBugz Python APIgetattr используется для беспрепятственной передачи вызовов методов веб-службе:

class FogBugz:
    ...

    def __getattr__(self, name):
        # Let's leave the private stuff to Python
        if name.startswith("__"):
            raise AttributeError("No such attribute '%s'" % name)

        if not self.__handlerCache.has_key(name):
            def handler(**kwargs):
                return self.__makerequest(name, **kwargs)
            self.__handlerCache[name] = handler
        return self.__handlerCache[name]
    ...

Когда кто-то вызывает FogBugz.search(q='bug'), они не получают вызова метода search. Вместо этого getattr обрабатывает вызов, создавая новую функцию, которая обертывает метод makerequest, который создает соответствующий HTTP-запрос к веб-API. Любые ошибки будут отправлены веб-службой и возвращены пользователю.

Таким же образом можно создавать полу-нестандартные типы.

user13876 30.12.2008 12:54

перечислять

Оберните итерацию с помощью enumerate, и она выдаст элемент вместе с его индексом.

Например:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Рекомендации:

Я удивлен, что это обычно не рассматривается в учебных пособиях, посвященных спискам Python.

Draemon 27.11.2008 07:06

это такая классная функция / функция

hasen 17.03.2009 04:02

я думаю, что это устарело в python3

Berry Tsakala 22.06.2009 01:04

И все это время я кодировал так: for i in range (len (a)): ... и затем использовал [i] для получения текущего элемента.

Fernando Martin 22.06.2009 20:35

@ Берри Цакала: Насколько мне известно, он не устарел.

JAB 27.07.2009 21:36

короче, чем использование zip и count для индекса, элемент в zip (itertools.count (), a): print (index, item)

Yoo 30.09.2009 00:32

Отличная особенность, +1. @Draemon: это фактически описано в учебнике Python, который поставляется вместе с Python (есть раздел о различных конструкциях цикла), поэтому я всегда удивляюсь, что об этом так мало известно.

Edan Maor 18.10.2009 13:03

Это хорошо, когда вы выполняете итерацию более чем одного цикла одновременно.

dassouki 18.02.2010 15:05

Черт возьми, это круто. for i in xrange (len (a)): всегда была моей наименее любимой идиомой о Python.

Personman 15.04.2010 20:22

@ Берри Цакала: определенно не рекомендуется.

ncoghlan 01.02.2011 09:09

Извините за мое незнание, но этого недостаточно, чтобы просто сделать: a = ["a","b","c"] >>> for x in enumerate(a): ... print x, почему вы делаете for index, item in enumerate(a): print index, item

Trufa 04.04.2011 07:16

Я всегда взламывал idx, elem in itertools.izip(itertools.count(), iterable): ...

Jeeyoung Kim 24.05.2011 03:39

@Tufa: возможно, вы не захотите использовать индекс и элемент в одном выражении. В этом простом примере ваш код эквивалентен, но в более сложном сценарии он не сможет делать все, что может делать for inx, itm in enumerate(a):.

Tomas Aschan 23.06.2011 16:13

for i in range(len(a)) по-прежнему намного лучше, чем for (int i=0;i<a.size();i++) ....

Gravity 28.07.2011 08:53

enumerate может начинаться с произвольного индекса, необязательно 0. Пример: 'for i, item in enumerate (список, start = 1): print i, item' начнет перечисление с 1, а не с 0.

dmitry_romanov 22.08.2011 15:00

Не устарело в Py3K docs.python.org/py3k/library/…

Léo Germond 16.09.2011 11:53

Тернарный оператор

>>> 'ham' if True else 'spam'
'ham'
>>> 'ham' if False else 'spam'
'spam'

Это было добавлено в 2.5, до этого вы могли использовать:

>>> True and 'ham' or 'spam'
'ham'
>>> False and 'ham' or 'spam'
'spam'

Однако, если значения, с которыми вы хотите работать, будут считаться ложными, есть разница:

>>> [] if True else 'spam'
[]
>>> True and [] or 'spam'
'spam'

До 2.5, "foo = bar and 'ham' or 'spam'"

a paid nerd 11.05.2009 08:30

@a платный ботаник - не совсем так: 1 == 1 и 0 или 3 => 3. И замыкает на 0 (поскольку это эквивалентно False - то же самое с "" и None).

hbn 24.01.2011 00:45

Вы можете создать словарь из набора последовательностей длиной 2. Очень удобно, когда у вас есть список значений и список массивов.

>>> dict([ ('foo','bar'),('a',1),('b',2) ])
{'a': 1, 'b': 2, 'foo': 'bar'}

>>> names = ['Bob', 'Marie', 'Alice']
>>> ages = [23, 27, 36]
>>> dict(zip(names, ages))
{'Alice': 36, 'Bob': 23, 'Marie': 27}

self.data = {} _i = 0 для ключей в self.VDESC.split (): self.data [keys] = _data [_i] _i + = 1 Я заменил свой код этим однострочным :) self.data = dict (zip (self.VDESC.split (), _data)) Спасибо за полезный совет.

Gökhan Sever 29.09.2009 06:32

Также помогает в Python2.x, где нет синтаксиса понимания слов. Вы можете написать dict((x, x**2) for x in range(10)).

Marian 29.05.2010 15:57

Распаковка кортежей в циклах for, составлении списков и выражениях генератора:

>>> l=[(1,2),(3,4)]
>>> [a+b for a,b in l ] 
[3,7]

Полезно в этой идиоме для перебора пар (ключ, данные) в словарях:

d = { 'x':'y', 'f':'e'}
for name, value in d.items():  # one can also use iteritems()
   print "name:%s, value:%s" % (name,value)

печатает:

name:x, value:y
name:f, value:e

Это также полезно при замене l на zip(something).

asmeurer 28.12.2010 09:00

«Распаковка» в параметры функции

def foo(a, b, c):
        print a, b, c

bar = (3, 14, 15)
foo(*bar)

При выполнении отпечатков:

3 14 15

Это каноническая альтернатива старой встроенной функции apply ().

Jim Dennis 26.06.2010 03:11

Объекты в логическом контексте

Пустые кортежи, списки, словари, строки и многие другие объекты эквивалентны False в логическом контексте (а непустые эквивалентны True).

empty_tuple = ()
empty_list = []
empty_dict = {}
empty_string = ''
empty_set = set()
if empty_tuple or empty_list or empty_dict or empty_string or empty_set:
  print 'Never happens!'

Это позволяет логическим операциям возвращать один из его операндов вместо True / False, что полезно в некоторых ситуациях:

s = t or "Default value" # s will be assigned "Default value"
                         # if t is false/empty/none

на самом деле это не рекомендуется, вы должны использовать «новый» s = t if t else «значение по умолчанию»

Tom 27.08.2009 14:52

Первоклассность всего («все есть объект») и хаос, который это может вызвать.

>>> x = 5
>>> y = 10
>>> 
>>> def sq(x):
...   return x * x
... 
>>> def plus(x):
...   return x + x
... 
>>> (sq,plus)[y>x](y)
20

Последняя строка создает кортеж, содержащий две функции, затем оценивает y> x (True) и использует это как индекс кортежа (путем преобразования его в int, 1), а затем вызывает эту функцию с параметром y и показывает результат.

Для дальнейшего злоупотребления, если вы возвращали объект с индексом (например, список), вы можете добавить дополнительные квадратные скобки в конце; если содержимое было вызываемым, добавляйте скобки и т. д. Для дополнительного извращения используйте результат такого кода как выражение в другом примере (т.е. замените y> x этим кодом):

(sq,plus)[y>x](y)[4](x)

Это демонстрирует два аспекта Python - философию «все есть объект», доведенную до крайности, и методы, с помощью которых неправильное или плохо продуманное использование синтаксиса языка может привести к полностью нечитаемому, не поддерживаемому спагетти-коду, который умещается в одном выражении. .

зачем тебе вообще это делать? вряд ли это обоснованная критика языка, чтобы показать, как им можно намеренно злоупотреблять. случайное злоупотребление допустимо, но никогда не произойдет случайно.

Christian Oudard 02.01.2009 21:41

@Gorgapor: последовательность Python и отсутствие исключений и особых случаев - вот что делает его легким в изучении и, по крайней мере, для меня, красивым. Любой мощный инструмент, применяемый неправомерно, может вызвать «хаос». Вопреки вашему мнению, я считаю, что возможность индексировать последовательность функций и вызывать ее в одном выражении - это мощная и полезная идиома, и я использовал ее не раз с пояснительными комментариями.

Don O'Donnell 25.01.2010 11:07

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

Christian Oudard 25.01.2010 16:21

@Gorganpor: Извини, я хотел адресовать свой комментарий Дэну Удэю, а не тебе. Я полностью с вами согласен.

Don O'Donnell 26.01.2010 07:07

Назначение и удаление срезов:

>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:5] = [42]
>>> a
[42, 5, 6, 7, 8, 9]
>>> a[:1] = range(5)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[::2]
>>> a
[1, 3, 5, 7, 9]
>>> a[::2] = a[::-2]
>>> a
[9, 3, 5, 7, 1]

Примечание: при назначении расширенным слайсам (s[start:stop:step]) назначенная итерация должна иметь ту же длину, что и слайс.

Конструктор dict принимает аргументы ключевого слова:

>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}

Пока аргументы ключевого слова являются действительными идентификаторами (именами) Python. Вы не можете использовать: dict (1 = "one", two = 2 ...), потому что "1" не является допустимым идентификатором, даже если это совершенно допустимый ключ словаря.

Jim Dennis 26.06.2010 02:45

Идеально подходит для копирования и обновления: base = {'a': 4, 'b': 5}; обновлено = dict (основание, c = 5)

Tomek Paczkowski 12.01.2012 13:20

Получите дерево синтаксического анализа регулярного выражения Python для отладки вашего регулярного выражения.

Регулярные выражения - отличная особенность Python, но их отладка может быть сложной задачей, и слишком легко ошибиться в регулярном выражении.

К счастью, python может распечатать дерево синтаксического анализа регулярных выражений, передав недокументированный экспериментальный скрытый флаг re.DEBUG (на самом деле 128) в re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Как только вы поймете синтаксис, вы сможете обнаружить свои ошибки. Здесь мы видим, что я забыл сбежать от [] в [/font].

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

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)

За исключением синтаксического анализа HTML с использованием регулярных выражений, это медленный и болезненный процесс. Даже встроенный модуль синтаксического анализатора html не использует регулярные выражения для выполнения работы. И если модуль html вам не нравится, существует множество модулей синтаксического анализатора XML / HTML, которые справятся с этой задачей без необходимости изобретать колесо.

BatchyX 27.03.2010 00:59

Ссылка на документацию по синтаксису вывода была бы замечательной.

Personman 15.04.2010 20:13

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

Cahit 15.07.2010 03:27

Встроенные кодеки base64, zlib и rot13

Строки имеют методы encode и decode. Обычно это используется для преобразования str в unicode и наоборот, например с u = s.encode('utf8'). Но есть и другие удобные встроенные кодеки. Сжатие и распаковка с помощью zlib (и bz2) доступны без явного импорта:

>>> s = 'a' * 100
>>> s.encode('zlib')
'x\x9cKL\xa4=\x00\x00zG%\xe5'

Точно так же вы можете кодировать и декодировать base64:

>>> 'Hello world'.encode('base64')
'SGVsbG8gd29ybGQ=\n'
>>> 'SGVsbG8gd29ybGQ=\n'.decode('base64')
'Hello world'

И, конечно же, можно rot13:

>>> 'Secret message'.encode('rot13')
'Frperg zrffntr'

К сожалению, это перестанет работать в Python 3

Marius Gedminas 18.06.2009 22:51

Ой, он перестанет работать? Это очень плохо :/. Я просто подумал, насколько хороша эта функция. Потом увидел твой комментарий.

FeatureCreep 01.01.2010 23:56

Ужасно, base64 был очень полезен в интерактивных сессиях, обрабатывающих данные из Интернета.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 14.05.2010 00:39

На мой взгляд, это какой-то тип кодирования / декодирования, но с другой стороны, должен быть «только один путь к этому», и я думаю, что эти вещи лучше поместить в отдельный модуль!

Joschua 23.06.2010 18:42

Очевидно, антигравитационный модуль. xkcd # 353

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

user13876 30.12.2008 12:43

Что действительно работает. Попробуйте поставить "импорт антигравитации" в новейшую версию Py3K.

Andrew Szeto 05.06.2009 13:11

@ Эндрю Сзето ... что он делает?

Jiaaro 02.12.2009 21:13

@ Джим Роберт: открывает веб-браузер на сайт xkcd;)

poke 28.03.2010 17:53

модуль skynet тоже весьма полезен ...

Tshirtman 03.03.2012 04:38

Генераторы

Я думаю, что многие начинающие разработчики Python обходятся без генераторов, не понимая, для чего они нужны, и не осознавая их возможности. Только когда я прочитал презентацию PyCon Дэвида М. Бизли о генераторах (она доступна здесь), я понял, насколько они полезны (действительно важны). Эта презентация осветила то, что было для меня совершенно новым способом программирования, и я рекомендую его всем, кто не имеет глубокого понимания генераторов.

Ух ты! Мозг у меня сгорел, и это были только первые 6 частей. Начиная с 7, мне приходилось рисовать картинки, чтобы посмотреть, действительно ли я понимаю, что происходит с конвейерами многопроцессорной / многопоточной / многопоточной обработки. Потрясающие вещи!

Peter Rowell 10.11.2008 22:06

+1 за ссылку на презентацию

Mark Heath 01.10.2010 14:13

Заполнение вкладки интерактивного переводчика

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

Вам также нужно будет установить переменную среды PYTHONSTARTUP.

Это очень полезная функция. Настолько, что у меня есть простой скрипт для его включения (плюс пара других улучшений интроспекции): pixelbeat.org/scripts/inpy

pixelbeat 13.10.2008 02:49

IPython дает вам это плюс множество других полезных вещей

akaihola 10.01.2009 06:47

Это было бы более полезно в приглашении pdb, чем в обычном приглашении python (поскольку IPython в любом случае служит этой цели). Однако это, похоже, не работает в приглашении pdb, вероятно, потому, что pdb связывает свою собственную вкладку для вкладки (что менее полезно). Я попытался вызвать parse_and_bind () в командной строке pdb, но это все равно не сработало. Альтернатива получения приглашения pdb с помощью IPython требует больше работы, поэтому я стараюсь не использовать ее.

haridsv 02.04.2010 02:46

Нашел этот рецепт, но у меня это не сработало (с использованием python 2.6): code.activestate.com/recipes/498182

haridsv 02.04.2010 02:57

@haridsv - easy_install ipdb - тогда вы можете использовать import ipdb; ipdb.set_trace()

Doug Harris 21.05.2010 02:03

Для меня лучшим советом было использовать try: except: else :. Я забыл об остальном в блоке try

neves 14.07.2010 03:32

На osx [и я представляю себе другие системы, использующие libedit] вы должны использовать readline.parse_and_bind ("bind ^I rl_complete").

Foo Bah 10.02.2011 18:20

Python имеет GOTO

... и это реализовано внешний модуль на чистом Python :)

from goto import goto, label
for i in range(1, 10):
    for j in range(1, 20):
        for k in range(1, 30):
            print i, j, k
            if k == 3:
                goto .end # breaking out from a deeply nested loop
label .end
print "Finished"

Может быть, лучше оставить эту функцию скрытой.

James McMahon 16.10.2008 16:32

Что ж, фактическая скрытая функция здесь - это механизм, используемый для реализации GOTO.

Constantin 16.10.2008 19:21

Конечно, для выхода из вложенного цикла вы можете просто вызвать исключение, не так ли?

shylent 14.11.2009 17:02

+1 первый, о котором я вообще не знал.

SingleNegationElimination 17.11.2009 21:55

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

SingleNegationElimination 17.11.2009 21:57

@shylent, правильный способ выйти из вложенного цикла - это поместить цикл в функцию и вернуться из функции

Christian Oudard 16.12.2009 20:41

Внешние модули не должны включаться в этот список. GOTO не является функцией Python.

Nick Perkins 21.09.2011 00:19

@TokenMacGuy: не в Python. Исключения используются внутри для завершения циклов с помощью StopIteration. Исключения вовсе не исключение.

e-satis 24.12.2011 19:15

Использование динамической природы Python для создания приложений config в синтаксисе Python. Например, если у вас были следующие в файле конфигурации:

{
  "name1": "value1",
  "name2": "value2"
}

Тогда вы могли бы банально прочитать это так:

config = eval(open("filename").read())

Я согласен. Я начал использовать файл settings.py или config.py, который затем загружаю как модуль. Несомненно, это лучше, чем дополнительные шаги по синтаксическому анализу файлов некоторых других форматов.

monkut 14.10.2008 05:39

Я вижу, что это становится проблемой безопасности.

Richard Waite 01.12.2008 22:56

Может быть, но иногда это не так. В таких случаях это круто.

recursive 01.01.2009 12:30

Python может быть гораздо более выразительным языком конфигурации, чем любое количество файлов XML или INI. Я пытаюсь избежать явной конфигурации, используя только сценарий вызова, который «импортирует myapp; приложение = myapp.Application (...); app.run () ». Параметры по умолчанию разумны, но их можно изменить с помощью аргументов конструктора.

bobince 17.03.2009 05:31

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

bobince 17.03.2009 05:33

Это смелое решение даже для не враждебной среды. eval () - это заряженное оружие, требующее особой осторожности при обращении. С другой стороны, использование JSON (теперь в stdlib 2.6) намного безопаснее и переносимо для переноса конфигурации.

Berk D. Demir 22.03.2009 21:46

Я бы никогда не одобрил обзор кода, который содержал eval.

a paid nerd 11.05.2009 08:29

@ Ричард Уэйт: Обычно это проблема безопасности, если злоумышленник может изменить ваш файл конфигурации ...

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 14.05.2010 01:03

Я согласен, это чрезвычайно полезно во многих быстрых и грязных сценариях. Но лучше использовать execfile вместо eval + open + read.

Jukka Suomela 21.07.2010 04:21

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

Escualo 28.07.2010 08:05

Тогда почему Django хранит настройки сайта в файле .py (включая пароль db)? Они в своем уме, не используют eval () или что-то мне не хватает?

Agos 31.07.2010 03:25

Мне лично не нравится использовать eval() ни для чего, особенно для настроек. Я всегда оборачиваю настройки Django вокруг ConfigParser и сохраняю актуальную информацию в файле с защищенными правами доступа. Как сказал Расмус Лердорф: «Если eval () - это ответ, вы почти наверняка задаете неправильный вопрос».

AdmiralNemo 31.07.2010 05:50

eval () имеет те же проблемы безопасности, что и import, поэтому отказать сценарию, который использует его для проблем безопасности, не имеет смысла. Это обычная проблема, заключающаяся в том, чтобы никогда не исключать ненадежный пользовательский ввод, но если файл заканчивается на .py и импортируется, он все равно запускается. Причина использования импорта заключается в том, что он аккуратно помещает вашу конфигурацию в другое пространство имен. Вы также можете использовать execfile (ConfigFile, ConfigDict) для хранения файлов конфигурации в словаре.

Perkins 14.01.2012 01:12

нет необходимости в eval, назовите свой dict (config) и импортируйте его из своего модуля… (из configfile import config)

Tshirtman 04.03.2012 02:36

Повторная привязка параметров вложенной функции

def create_printers(n):
    for i in xrange(n):
        def printer(i=i): # Doesn't work without the i=i
            print i
        yield printer

он работает без него, но иначе. :-)

u0b34a0f6ae 13.12.2009 18:35

Нет, без него не работает. Опустите i = i и посмотрите разницу между map (apply, create_printers (10)) и map (apply, list (apply_printers (10))), где преобразование в список потребляет генератор, и теперь все десять функций принтера привязаны к i. с тем же значением: 9, где вызов их по одному вызывает их до того, как следующая итерация генератора изменит, к которому привязан int i во внешней области.

ironfroggy 15.12.2009 05:16

Я думаю, что @ kaizer.se говорит, что когда вы опускаете i=i, i в функции printer ссылается на i из цикла for, а не на локальный i, который создается при создании новой функции printer с ключевым словом i=i arg. Таким образом, он по-прежнему работает (он дает функции, каждая из которых имеет доступ к закрытию), но он работает не так, как вы ожидаете, без явного создания локальной переменной.

Sean Vieira 10.03.2011 01:57

Небольшая ошибка питона. Обычный быстрый способ объединить список строк:

''.join(list_of_strings)

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

Christian Oudard 02.01.2009 21:37

Да, я знаю, почему это происходит - но узнал бы кто-нибудь об этом, если бы им не сказали?

Martin Beckett 03.01.2009 00:28

Обнаружить? Это тоже довольно сложно запомнить, и я использовал python, так как до того, как появились методы om strings.

kaleissin 20.01.2009 16:48

Если это слишком уродливо для вас, вы можете написать то же самое, что и str.join('',list_of_strings), но другие питонисты могут насмехаться над вами за попытку написать java.

SingleNegationElimination 17.11.2009 22:04

@TokenMacGuy: причина, по которой предпочтительнее '' .join ([...]), заключается в том, что многие люди часто путают порядок аргументов в string.join (..., ...); поставив '.join (), все станет яснее

Lie Ryan 31.10.2010 02:32

Я почти уверен, что единственная причина, по которой большинство питонистов используют "".join(iterable) вместо str.join("",iterable), заключается в том, что он на 4 символа короче.

SingleNegationElimination 31.10.2010 03:45

@TokenMacGuy Нет. А что плохого в том, чтобы разделить и присоединиться к классу str? Это легко запомнить и кстати. это пример того, что «практичность лучше чистоты».

Joschua 29.12.2010 14:39

импортная антигравитация

этот ответ уже был дан

Davide 18.12.2008 20:01

Приватные методы и сокрытие данных (инкапсуляция)

В Python есть обычная идиома для обозначения методов и других членов класса, которые не предназначены для того, чтобы быть частью внешнего API класса, давая им имена, начинающиеся с подчеркивания. Это удобно и очень хорошо работает на практике, но создает ложное впечатление, что Python не поддерживает истинную инкапсуляцию частного кода и / или данных. Фактически, Python автоматически предоставляет вам лексические замыкания, что позволяет очень легко инкапсулировать данные гораздо более надежным способом, когда ситуация действительно этого требует. Вот надуманный пример класса, использующего эту технику:

class MyClass(object):
  def __init__(self):

    privateData = {}

    self.publicData = 123

    def privateMethod(k):
      print privateData[k] + self.publicData

    def privilegedMethod():
      privateData['foo'] = "hello "
      privateMethod('foo')

    self.privilegedMethod = privilegedMethod

  def publicMethod(self):
    print self.publicData

А вот надуманный пример его использования:

>>> obj = MyClass()
>>> obj.publicMethod()
123
>>> obj.publicData = 'World'
>>> obj.publicMethod()
World
>>> obj.privilegedMethod()
hello World
>>> obj.privateMethod()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateMethod'
>>> obj.privateData
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateData'

Ключ в том, что privateMethod и privateData на самом деле вообще не являются атрибутами obj, поэтому к ним нельзя получить доступ извне, и они не отображаются в dir() или аналогичных. Это локальные переменные в конструкторе, полностью недоступные за пределами __init__. Однако из-за магии замыканий они действительно являются переменными для каждого экземпляра с тем же временем жизни, что и объект, с которым они связаны, даже несмотря на то, что нет никакого способа получить к ним доступ извне, кроме как (в этом примере) путем вызова privilegedMethod. Часто такая очень строгая инкапсуляция является излишней, но иногда она действительно может быть очень удобна для поддержания безупречной чистоты API или пространства имен.

В Python 2.x единственный способ иметь изменяемое частное состояние - использовать изменяемый объект (такой как dict в этом примере). Многие отмечали, насколько это может раздражать. Python 3.x снимет это ограничение, введя ключевое слово nonlocal, описанное в PEP 3104.

это почти никогда не бывает хорошей идеей.

Christian Oudard 02.01.2009 21:38

«Это локальные переменные в конструкторе, полностью недоступные за пределами в этом». Неправда: >>> [c.cell_contents для c в obj.privilegedMethod.func_closure] -> [{'foo': 'hello'}, <function privateMethod at 0x65530>]

Miles 22.06.2009 05:34

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

Jeffrey Jose 27.05.2010 23:35

Использование аргументов ключевого слова как присваивания

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

funcs = [] 
for k in range(10):
     funcs.append( lambda: k)

>>> funcs[0]()
9
>>> funcs[7]()
9

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

funcs = [] 
for k in range(10):
     funcs.append( lambda k = k: k)

>>> funcs[0]()
0
>>> funcs[7]()
7

Менее хакерский способ сделать это (imho) - просто использовать отдельную функцию для создания лямбда-выражений, которые не закрываются для переменной цикла. Как это: def make_lambda(k): return lambda: k.

Jason Orendorff 29.01.2010 00:03

«менее хакерский»? .... это личное предпочтение, я думаю, но это основная штука Python, а не хакерство. Вы, конечно, можете структурировать его (используя функции), чтобы читателю не нужно было понимать, как работают аргументы Python по умолчанию, - но если вы действительно понимаете, как работают аргументы по умолчанию, вы прочитаете "lambda: k=k:k" и сразу поймете, что он «сохраняет» текущее значение «k» (когда создается лямбда) и присоединение его к самой лямбде. То же самое работает и с обычными функциями def.

Nick Perkins 21.09.2011 00:34

Ответ Джейсона Орендорфа правильный, но именно так мы имитировали замыкания в Python, прежде чем Гвидо окончательно согласился с тем, что вложенные области видимости - хорошая идея.

Kragen Javier Sitaker 12.01.2012 08:23

Замена метода для экземпляра объекта

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

>>> class C(object):
...     def fun(self):
...         print "C.a", self
...
>>> inst = C()
>>> inst.fun()  # C.a method is executed
C.a <__main__.C object at 0x00AE74D0>
>>> instancemethod = type(C.fun)
>>>
>>> def fun2(self):
...     print "fun2", self
...
>>> inst.fun = instancemethod(fun2, inst, C)  # Now we are replace C.a by fun2
>>> inst.fun()  # ... and fun2 is executed
fun2 <__main__.C object at 0x00AE74D0>

Как мы видим, C.a был заменен на fun2() в экземпляре inst (self не изменился).

В качестве альтернативы мы можем использовать модуль new, но он устарел, начиная с Python 2.6:

>>> def fun3(self):
...     print "fun3", self
...
>>> import new
>>> inst.fun = new.instancemethod(fun3, inst, C)
>>> inst.fun()
fun3 <__main__.C object at 0x00AE74D0>

Узел: Это решение не должно использоваться в качестве общей замены механизма наследования! Но это может быть очень удобно в некоторых конкретных ситуациях (отладка, насмешка).

Предупреждение: Это решение не будет работать для встроенных типов и для новых классов стилей, использующих слоты.

Лично я предпочитаю оставлять instancemethod классам; обычно так, чтобы поведение привязки foo.method работало нормально. Если я привязываю себя явно, я вместо этого использую functools.partial, который дает тот же эффект, но делает более ясным, что поведение привязки является явным.

SingleNegationElimination 28.07.2011 18:15

Обращение к пониманию списка по мере его создания ...

Вы можете ссылаться на составление списка с помощью символа '_ [1]'. Например, следующая функция присваивает уникальность списку элементов без изменения их порядка, ссылаясь на его понимание списка.

def unique(my_list):
    return [x for x in my_list if x not in locals()['_[1]']]

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

Kiv 01.01.2009 18:47

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

Rory 28.01.2009 02:12

Великолепно, буквально вчера я это искал!

Rob Golding 02.06.2009 13:28

не лучшая идея как по алгоритмическим, так и по практическим причинам. Алгоритмически это даст вам линейный поиск по списку до сих пор на каждой итерации, изменяя ваш цикл O (n) на O (n ** 2); гораздо лучше потом просто составить список в набор. На практике это недокументировано, может измениться и, вероятно, не работает в ironpython / jython / pypy.

llimllib 18.06.2009 08:04

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

Marius Gedminas 18.06.2009 22:48

Если вы хотите ссылаться на список при его создании, используйте обычный цикл. Это очень зависит от реализации - CPython использует скрытое имя в локальном dict, потому что это удобно, но другие реализации не обязаны делать то же самое.

ncoghlan 01.02.2011 10:02

набор / заморозка

Вероятно, встроенная функция python, которую легко упустить из виду, - это "set / frozenset".

Полезно, когда у вас есть список, подобный этому, [1,2,1,1,2,3,4], и вам нужны только такие уникальные объекты [1,2,3,4].

Используя set (), вы получите:

>>> x = [1,2,1,1,2,3,4] 
>>> 
>>> set(x) 
set([1, 2, 3, 4]) 
>>>
>>> for i in set(x):
...     print i
...
1
2
3
4

И, конечно же, чтобы получить количество уникальных посетителей в списке:

>>> len(set([1,2,1,1,2,3,4]))
4

Вы также можете узнать, является ли список подмножеством другого списка, используя set (). Issubset ():

>>> set([1,2,3,4]).issubset([0,1,2,3,4,5])
True

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

myset = {1,2,3,4}

а также установить понимание:

{x for x in stuff}

Больше подробностей: http://docs.python.org/library/stdtypes.html#set

Также полезно в случаях, когда словарь использовался только для проверки наличия значения.

Jacek Konieczny 20.03.2010 13:20

Я использую набор примерно столько же, сколько кортеж и список.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 14.05.2010 00:42

для подмножеств, я считаю, что это issubset, а не isasubset. в любом случае оператор подмножества <= в любом случае лучше.

wim 19.07.2011 15:31

вы также можете выполнять понимание dict в python 2.7 следующим образом {x: x * 2 for x in range (3)} Это, вероятно, сбивает с толку, если вы не знаете, что делаете, imho

Hassek 25.07.2011 05:56

Функциональная поддержка.

Генераторы и выражения генераторов, в частности.

Ruby снова сделал это мейнстримом, но Python тоже может это сделать. Не так распространен в библиотеках, как в Ruby, что очень плохо, но мне больше нравится синтаксис, он проще.

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

При отладке сложных структур данных пригодится модуль pprint.

Цитата из документов ..

>>> import pprint    
>>> stuff = sys.path[:]
>>> stuff.insert(0, stuff)
>>> pprint.pprint(stuff)
[<Recursion on list with id=869440>,
 '',
 '/usr/local/lib/python1.5',
 '/usr/local/lib/python1.5/test',
 '/usr/local/lib/python1.5/sunos5',
 '/usr/local/lib/python1.5/sharedmodules',
 '/usr/local/lib/python1.5/tkinter']

pprint также хорош для печати словарей в doctests, так как он всегда сортирует вывод по ключам

akaihola 10.01.2009 07:06

>>> from functools import partial
>>> bound_func = partial(range, 0, 10)
>>> bound_func()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> bound_func(2)
[0, 2, 4, 6, 8]

не совсем скрытая функция, но частичная чрезвычайно полезна для поздней оценки функций.

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

См. документация.

Я бы хотел, чтобы каррификация добавила достойного оператора в Python.

fulmicoton 17.03.2009 04:13

is_ok() and "Yes" or "No"

Это странно. Интересно, но странно. >>> Верно и «Да» или «Нет», «Да» >>> Ложно и «Да» или «Нет», «Нет» >>> x = «Да» >>> y = «Нет» >>>> >> Ложь и х или у

monkut 27.11.2008 06:41

Предпочтительный способ сделать это в Python 2.5 или новее - «'Yes' if is_ok () else 'No'».

Paul Fisher 27.11.2008 06:43

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

M. Utku ALTINKAYA 27.11.2008 06:57

«Предпочтительный» аргумент открыт для обсуждения, потому что в этом случае порядок выполнения совпадает с логическим порядком, в то время как «Да», если True, иначе «Нет» не такой.

M. Utku ALTINKAYA 27.11.2008 06:59

«Предпочтительный» В этом случае означает, что условный оператор работает должным образом для всех возможных операндов. В частности, True and False or True - это правда, но False if True else True - ложь, что почти наверняка соответствует вашим ожиданиям. Это особенно важно, когда операнды имеют побочные эффекты, и условный оператор НИКОГДА оценивает более одного из своих условных предложений.

SingleNegationElimination 31.12.2009 02:54

Это часто используемая функция во многих языках [особенно в bash, где && || синтаксис используется для имитации тернарного оператора]

Foo Bah 10.02.2011 18:15

... что dict.get() имеет значение значение по умолчанию, равное None, что позволяет избежать ошибок KeyErrors:

In [1]: test = { 1 : 'a' }

In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'>              Traceback (most recent call last)

&lt;ipython console&gt; in <module>()

<type 'exceptions.KeyError'>: 2

In [3]: test.get( 2 )

In [4]: test.get( 1 )
Out[4]: 'a'

In [5]: test.get( 2 ) == None
Out[5]: True

и даже указать это «на месте происшествия»:

In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True

И вы можете использовать setdefault(), чтобы значение было установлено и возвращено, если оно не существует:

>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar

Вы можете легко транспонировать массив с помощью zip.

a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]

В основном zip(*a)расстегиваетa. Так что если b = zip(a), то a == zip(*b).

asmeurer 28.12.2010 08:27

map (None, * a) может пригодиться, если ваши кортежи имеют разную длину: map (None, * [(1,2), (3,4,5), (5,)]) => [(1 , 3, 5), (2, 4, Нет), (Нет, 5, Нет)]

hbn 24.01.2011 00:37

Только что нашел эту функцию на docs.python.org/library/functions.html и собирался поделиться ею здесь. Похоже, ты меня опередил.

Adam Fraser 28.05.2011 01:51

Я помню, как это работает: «zip * превращает список пар в пару списков» (и наоборот)

Adam 11.01.2012 02:45

Отрицательный раунд

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

>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'

Примечание:round() всегда возвращает число с плавающей запятой, str(), использованное в приведенном выше примере, потому что математика с плавающей запятой неточна, а в версии 2.x второй пример может печатать как 1234.5700000000001. Также см. Модуль decimal.

Очень часто мне приходится округлять число до кратного. Например, округлите 17 до числа, кратного 5 (15). Но раунд Python не позволяет мне этого сделать! ИМО, он должен быть структурирован как round(num, precision=1) - round "num" to the nearest multiple of "precision"

Ponkadoodle 16.05.2010 10:56

@wallacoloo в чем дело с (17/5) * 5? Разве это не коротко и выразительно?

silviot 26.08.2010 23:39

@silviot попробуйте это с (19/5) * 5. 19, округленное до ближайшего 5, должно быть 20, не так ли? Но это, кажется, возвращает 15. Кроме того, это полагается на правила целочисленного деления Python 2.x. Это не будет работать так же в 3.x. Самое краткое и правильное решение imo: roundNearest = lambda n, m: round(float(n)/m)*m

Ponkadoodle 17.12.2010 04:21

Или вообще roundNearest = lambda n, m: (n + (m/2)) / m * m. Это в два раза быстрее, чем при использовании round(float) в моей системе.

Mikel 24.01.2011 02:50

Переводчик внутри переводчика

Модуль код стандартной библиотеки позволяет вам включить собственный цикл чтения-оценки-печати в программу или запустить весь вложенный интерпретатор. Например. (скопировал мой пример из здесь)

$ python
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> shared_var = "Set in main console"
>>> import code
>>> ic = code.InteractiveConsole({ 'shared_var': shared_var })
>>> try:
...     ic.interact("My custom console banner!")
... except SystemExit, e:
...     print "Got SystemExit!"
... 
My custom console banner!
>>> shared_var
'Set in main console'
>>> shared_var = "Set in sub-console"
>>> import sys
>>> sys.exit()
Got SystemExit!
>>> shared_var
'Set in main console'

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

TurboGears использует это для большого эффекта, имея веб-консоль, из которой вы можете запрашивать состояние вашего живого веб-приложения.

Перегрузка оператора для встроенного set:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

Подробнее из справочника стандартной библиотеки: Типы наборов

В учебнике частично docs.python.org/tutorial/datastructures.html#sets

XTL 16.02.2012 11:58

Вы можете переопределить MRO класса с помощью метакласса

>>> class A(object):
...     def a_method(self):
...         print("A")
... 
>>> class B(object):
...     def b_method(self):
...         print("B")
... 
>>> class MROMagicMeta(type):
...     def mro(cls):
...         return (cls, B, object)
... 
>>> class C(A, metaclass=MROMagicMeta):
...     def c_method(self):
...         print("C")
... 
>>> cls = C()
>>> cls.c_method()
C
>>> cls.a_method()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(<class '__main__.A'>,)
>>> type(cls).__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)

Вероятно, это скрыто по уважительной причине. :)

Это игра с огнем и просьба о вечном проклятии. Лучше иметь вескую причину;)

gorsky 18.12.2009 13:20

Не работает с python 2.x. Вместо этого используйте __metaclass__ = MROMagicMeta.

Alexander Artemenko 15.07.2011 14:35

Встроенный reversed(). Во многих случаях это значительно упрощает итерацию.

быстрый пример:

for i in reversed([1, 2, 3]):
    print(i)

производит:

3
2
1

Однако reversed() также работает с произвольными итераторами, такими как строки в файле или выражения генератора.

Дзен Python

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Скрытый? OTOH, это один из плюсов Python.

Jeffrey Jose 27.05.2010 23:19

Мне нравится расцветка синтаксиса, особенно. для Dutch.

asmeurer 31.12.2010 07:42

Дубликат предыдущего ответа

e-satis 24.12.2011 19:23

Дубликат предыдущего ответа

warvariuc 04.03.2012 23:39

pdb - Отладчик Python

Как программист, одно из первых, что вам нужно для серьезной разработки программы, - это отладчик. У Python есть один встроенный модуль, который доступен в виде модуля под названием pdb (естественно, для Python DeBugger!).

http://docs.python.org/library/pdb.html

Объекты малых целых чисел (-5 .. 256) никогда не создавались дважды:


>>> a1 = -5; b1 = 256
>>> a2 = -5; b2 = 256
>>> id(a1) == id(a2), id(b1) == id(b2)
(True, True)
>>>
>>> c1 = -6; d1 = 257
>>> c2 = -6; d2 = 257
>>> id(c1) == id(c2), id(d1) == id(d2)
(False, False)
>>>

Редактировать: Объекты списка никогда не уничтожаются (только объекты в списках). Python имеет массив, в котором хранится до 80 пустых списков. Когда вы уничтожаете объект списка - python помещает его в этот массив, а когда вы создаете новый список - python получает последний добавленный список из этого массива:


>>> a = [1,2,3]; a_id = id(a)
>>> b = [1,2,3]; b_id = id(b)
>>> del a; del b
>>> c = [1,2,3]; id(c) == b_id
True
>>> d = [1,2,3]; id(d) == a_id
True
>>>

Эта функция зависит от реализации, поэтому полагаться на нее не стоит.

Denis Otkidach 27.10.2009 18:36

Как сказал Денис, не стоит полагаться на такое поведение. Это не работает, например, в PyPy, и ваш код будет ужасно ломаться, если вы попытаетесь его использовать.

asmeurer 28.12.2010 08:53

Создание словаря из двух последовательностей, имеющих связанные данные

In [15]: t1 = (1, 2, 3)

In [16]: t2 = (4, 5, 6)

In [17]: dict (zip(t1,t2))
Out[17]: {1: 4, 2: 5, 3: 6}

Моделирование третичного оператора с помощью и и или.

Операторы and and or в python возвращают сами объекты, а не логические значения. Таким образом:

In [18]: a = True

In [19]: a and 3 or 4
Out[19]: 3

In [20]: a = False

In [21]: a and 3 or 4
Out[21]: 4

Однако Py 2.5, похоже, добавил явный третичный оператор

    In [22]: a = 5 if True else '6'

    In [23]: a
    Out[23]: 5

Что ж, это работает, если вы уверены, что ваше предложение true не оценивается как False. пример:

>>> def foo(): 
...     print "foo"
...     return 0
...
>>> def bar(): 
...     print "bar"
...     return 1
...
>>> 1 and foo() or bar()
foo
bar
1

Чтобы понять это правильно, вам нужно немного больше:

>>> (1 and [foo()] or [bar()])[0]
foo
0

Однако это не так красиво. если ваша версия Python поддерживает это, используйте условный оператор.

>>> foo() if True or bar()
foo
0

Осторожно: >>> a и "" или ":(" вы всегда получите хмурое лицо в ответ, независимо от того, истинно оно или ложно.

Marius Gedminas 18.06.2009 23:00

Marius, только, если а ложь. В противном случае вы бы хотели, чтобы ":(" поскольку "" ложно.

Lakshman Prasad 19.06.2009 07:55

(falseValue, trueValue)[cond] - это более чистый (IMO) способ имитации тернарного оператора.

Ponkadoodle 16.05.2010 11:09

Модуль осмотреть - тоже классная функция.

Модуль spam в стандартном Python

Он используется для тестирования.

Выбрал из ctypes учебник. Попробуй сам:

>>> import __hello__
Hello world...
>>> type(__hello__)
<type 'module'>
>>> from __phello__ import spam
Hello world...
Hello world...
>>> type(spam)
<type 'module'>
>>> help(spam)
Help on module __phello__.spam in __phello__:

NAME
    __phello__.spam

FILE
    c:\python26\<frozen>

извините, почему и как вы бы это использовали?

cmcginty 21.07.2009 01:50

@Casey: прочтите раздел «Доступ к значениям, экспортированным из dll» в руководстве по ctypesstarship.python.net/crew/theller/ctypes/…

jfs 21.07.2009 23:27

Ваш пример непонятен.

Mikel 24.01.2011 06:56

Управление памятью

Python динамически выделяет память и использует сборку мусора для восстановления неиспользуемого пространства. Как только объект выходит за рамки и никакие другие переменные не ссылаются на него, он будет восстановлен. Мне не нужно беспокоиться о переполнении буфера и медленно растущих серверных процессах. Управление памятью также является функцией других динамических языков, но Python просто отлично с этим справляется.

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

re может вызывать функции!

Тот факт, что вы можете вызывать функцию каждый раз, когда что-то соответствует регулярному выражению, очень удобен. Здесь у меня есть пример замены каждого «Привет» на «Привет», «там» на «Фред» и т. д.

import re

def Main(haystack):
  # List of from replacements, can be a regex
  finds = ('Hello', 'there', 'Bob')
  replaces = ('Hi,', 'Fred,', 'how are you?')

  def ReplaceFunction(matchobj):
    for found, rep in zip(matchobj.groups(), replaces):
      if found != None:
        return rep

    # log error
    return matchobj.group(0)

  named_groups = [ '(%s)' % find for find in finds ]
  ret = re.sub('|'.join(named_groups), ReplaceFunction, haystack)
  print ret

if __name__ == '__main__':
  str = 'Hello there Bob'
  Main(str)
  # Prints 'Hi, Fred, how are you?'

Это безумие. Я понятия не имел, что это существует. классно. большое спасибо.

Jeffrey Jose 27.05.2010 23:13

Никогда раньше такого не видел, но лучшим примером может быть re.sub('[aeiou]', lambda match: match.group().upper()*3, 'abcdefghijklmnopqrstuvwxyz').

Don Spaulding 25.03.2011 20:14

Мне лично нравится 3 разных цитаты

str = "I'm a string 'but still I can use quotes' inside myself!"
str = """ For some messy multi line strings.
Such as
<html>
<head> ... </head>"""

Также круто: не нужно экранировать регулярные выражения, избежать ужасного салата с обратной косой чертой с помощью сырые струны:

str2 = r"\n" 
print str2
>> \n
Четыре different quotes, if you include '''
user1686 26.08.2009 21:07

Мне нравится, когда ' и " делают в коде примерно одно и то же. Моя IDE выделяет строки из двух разными цветами, и это позволяет легко отличать короткие строки (с ') от более длинных (с ").

asmeurer 28.12.2010 08:41

Одно слово: IPython

Самоанализ вкладок, красивая печать, %debug, управление историей, pylab, ... стоит потратить время, чтобы хорошо изучить.

Это не встроено в ядро ​​Python, не так ли?

Joshua Partogi 22.07.2009 10:16

Вы правы, это не так. И, вероятно, не без оснований. Но я безоговорочно рекомендую его любому программисту на Python. (Тем не менее, я настоятельно рекомендую отключить автоматический вызов. Когда он делает что-то, чего вы не ожидаете, может быть очень трудно понять, почему.)

Ken Arnold 25.07.2009 00:13

Еще я люблю IPython. Я пробовал BPython, но он был для меня слишком медленным (хотя я согласен, что в нем есть несколько интересных функций).

Denilson Sá Maia 04.08.2010 23:10

Перезагрузка модулей позволяет использовать стиль «живого кодирования». Но экземпляры класса не обновляются. Вот почему и как это обойти. Помните, все, да, все - это объект.

>>> from a_package import a_module
>>> cls = a_module.SomeClass
>>> obj = cls()
>>> obj.method()
(old method output)

Теперь вы меняете метод в a_module.py и хотите обновить свой объект.

>>> reload(a_module)
>>> a_module.SomeClass is cls
False # Because it just got freshly created by reload.
>>> obj.method()
(old method output)

Вот один из способов обновить его (но считайте, что он работает ножницами):

>>> obj.__class__ is cls
True # it's the old class object
>>> obj.__class__ = a_module.SomeClass # pick up the new class
>>> obj.method()
(new method output)

Это «работа ножницами», потому что внутреннее состояние объекта может отличаться от ожидаемого новым классом. Это работает для действительно простых случаев, но помимо этого pickle - ваш друг. Тем не менее, все же полезно понять, почему это работает.

+1 за предложение pickle (или cPickle). Несколько недель назад это было действительно полезно для меня.

Denilson Sá Maia 21.08.2010 00:51

Не очень скрыто, но у функций есть атрибуты:

def doNothing():
    pass

doNothing.monkeys = 4
print doNothing.monkeys
4

Это потому, что функции можно рассматривать как объекты с определенной функцией __call __ ().

Tomasz Zieliński 14.01.2010 19:06

Это потому, что функции можно рассматривать как дескрипторы с определенной функцией __call __ ().

Jeffrey Jose 27.05.2010 23:15

Подождите, а у __call__() тоже есть функция __call__()?

user142019 29.06.2011 18:20

Готов поспорить, что это функции __call __ () полностью вниз.

Chris Pickett 05.08.2011 21:17

Вы можете украсить функции классами - заменив функцию экземпляром класса:

class countCalls(object):
    """ decorator replaces a function with a "countCalls" instance
    which behaves like the original function, but keeps track of calls

    >>> @countCalls
    ... def doNothing():
    ...     pass
    >>> doNothing()
    >>> doNothing()
    >>> print doNothing.timesCalled
    2
    """
    def __init__ (self, functionToTrack):
        self.functionToTrack = functionToTrack
        self.timesCalled = 0
    def __call__ (self, *args, **kwargs):
        self.timesCalled += 1
        return self.functionToTrack(*args, **kwargs)

После небольшого объема работы модуль потоковой обработки становится удивительно простым в использовании. Этот декоратор изменяет функцию так, чтобы она выполнялась в собственном потоке, возвращая экземпляр класса-заполнителя вместо обычного результата. Вы можете проверить ответ, проверив placeolder.result, или дождаться его, вызвав placeholder.awaitResult ()

def threadify(function):
    """
    exceptionally simple threading decorator. Just:
    >>> @threadify
    ... def longOperation(result):
    ...     time.sleep(3)
    ...     return result
    >>> A= longOperation("A has finished")
    >>> B= longOperation("B has finished")

    A doesn't have a result yet:
    >>> print A.result
    None

    until we wait for it:
    >>> print A.awaitResult()
    A has finished

    we could also wait manually - half a second more should be enough for B:
    >>> time.sleep(0.5); print B.result
    B has finished
    """
    class thr (threading.Thread,object):
        def __init__(self, *args, **kwargs):
            threading.Thread.__init__ ( self )  
            self.args, self.kwargs = args, kwargs
            self.result = None
            self.start()
        def awaitResult(self):
            self.join()
            return self.result        
        def run(self):
            self.result=function(*self.args, **self.kwargs)
    return thr

Возможно, вас заинтересует модуль concurrent.futures, добавленный в Python 3.2.

ncoghlan 01.02.2011 09:53

ROT13 является допустимой кодировкой для исходного кода, когда вы используете правильное объявление кодировки в верхней части файла кода:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")

Большой! Обратите внимание, как байтовые строки воспринимаются буквально, но строки Unicode декодируются: попробуйте cevag h"Uryyb fgnpxbiresybj!"

u0b34a0f6ae 04.10.2009 05:12

к сожалению, он удален из py3k

mykhal 19.12.2009 21:33

Это хорошо для обхода антивируса.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 14.05.2010 00:37

Это не имеет ничего общего с кодировкой, это просто Python, написанный на валлийском языке. :-П

Olivier Verdier 14.07.2010 13:45

Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!

Manuel Ferreria 27.08.2010 02:08

видеть? вы можете писать непонятный код на любых языках, даже на python

Lie Ryan 31.10.2010 01:43

Урыыб fgnpxbiresybj! -> Привет, stackoverflow!

wim 14.07.2011 09:17

@ Мануэль Феррерия: извините, но я не мог понять, что вы сказали ... это ROT13 ??

amyassin 04.09.2011 04:58

@amyassin Я тоже был в шоке, пока не вспомнил про гугл и не нашел en.wiktionary.org/wiki/…

Jordan Reiter 19.10.2011 20:32

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

Однако просто добавьте ссылку на определение вашего класса, и все будет хорошо:

например, до:

class Bleh:
    pass

сейчас же,

class Blah:
    pass

Итак, маринованный сохраненный файл вашего пользователя содержит ссылку на Bleh, которая не существует из-за переименования. Исправление?

Bleh = Blah

просто!

Разумный хакер, но почему изменилось название класса? было ли это потому, что это противоречит чему-то другому? Выполнение такого рода действий сводит на нет любую выгоду, которую вы могли бы получить от переименования класса в первую очередь.

SingleNegationElimination 31.12.2009 02:42

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

Steven Sproat 01.01.2010 21:38

Тот факт, что ВСЕ является объектом и как таковой является расширяемым. Я могу добавить переменные-члены в качестве метаданных к функции, которую я определяю:

>>> def addInts(x,y): 
...    return x + y
>>> addInts.params = ['integer','integer']
>>> addInts.returnType = 'integer'

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

Большинство вещей - объекты; а некоторые объекты не так успешно принимают присвоение свойств.

user166390 21.10.2009 23:02

Встроенная функция getattr:

>>> class C():
    def getMontys(self):
        self.montys = ['Cleese','Palin','Idle','Gilliam','Jones','Chapman']
        return self.montys


>>> c = C()
>>> getattr(c,'getMontys')()
['Cleese', 'Palin', 'Idle', 'Gilliam', 'Jones', 'Chapman']
>>> 

Полезно, если вы хотите, чтобы функция диспетчеризации зависела от контекста. См. Примеры в Dive Into Python (Здесь)

Простой способ проверить, находится ли ключ в dict:

>>> 'key' in { 'key' : 1 }
True

>>> d = dict(key=1, key2=2)
>>> if 'key' in d:
...     print 'Yup'
... 
Yup

Надеюсь, это не скрыто для любого программиста, не являющегося новым Python!

u0b34a0f6ae 15.02.2010 15:10

Или даже новые, поскольку они представлены в учебнике.

XTL 16.02.2012 14:02

Классы как объекты первого класса (показаны в определении динамического класса)

Обратите внимание на использование крышки. Если этот конкретный пример выглядит как «правильный» подход к проблеме, внимательно пересмотрите ... несколько раз :)

def makeMeANewClass(parent, value):
  class IAmAnObjectToo(parent):
    def theValue(self):
      return value
  return IAmAnObjectToo

Klass = makeMeANewClass(str, "fred")
o = Klass()
print isinstance(o, str)  # => True
print o.theValue()        # => fred

Открытие изменяемых буферов

Использование Python от Буферный протокол до выставлять изменяемые байтовые буферы в Python (2.5 / 2.6).

(К сожалению, здесь нет кода. Требуется использование низкоуровневого API C или существующего модуля адаптера).

Расширение свойств (определенных как дескриптор) в подклассах

Иногда бывает полезно расширить (изменить) значение, "возвращаемое" дескриптором в подклассе. Это легко сделать с помощью super():

class A(object):
    @property
    def prop(self):
        return {'a': 1}

class B(A):
    @property
    def prop(self):
        return dict(super(B, self).prop, b=2)

Сохраните это в test.py и запустите python -i test.py (еще одна скрытая функция: опция -i выполняет сценарий и позволяет продолжить работу в интерактивном режиме):

>>> B().prop
{'a': 1, 'b': 2}

+1 свойства! Не могу насытиться ими.

Jeffrey Jose 27.05.2010 23:37

Питоническая идиома x = ... if ... else ... намного превосходит x = ... and ... or ..., и вот почему:

Хотя заявление

x = 3 if (y == 1) else 2

Эквивалентно

x = y == 1 and 3 or 2

если вы используете идиому x = ... and ... or ..., однажды вас может укусить такая запутанная ситуация:

x = 0 if True else 1    # sets x equal to 0

и поэтому не эквивалентен

x = True and 0 or 1   # sets x equal to 1

Чтобы узнать больше о том, как это сделать, см. Скрытые возможности Python.

Python может понимать любые цифры в Юникоде, а не только в виде ASCII:

>>> s = u'10585'
>>> s
u'\uff11\uff10\uff15\uff18\uff15'
>>> print s
10585
>>> int(s)
10585
>>> float(s)
10585.0

Что касается реализации Ником Джонсоном Класс недвижимости (просто демонстрация дескрипторов, конечно, а не замена встроенного), я бы включил сеттер, который вызывает AttributeError:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

    def __set__(self, obj, value):
       raise AttributeError, 'Read-only attribute'

Включение установщика делает это дескриптором данных, а не дескриптором метода / не-данных. Дескриптор данных имеет приоритет над словарями экземпляров. Теперь экземпляру не может быть назначен другой объект для имени свойства, и попытки назначить свойство вызовут ошибку атрибута.

Синтаксис распаковки был обновлен в последней версии, как видно на примере.

>>> a, *b = range(5)
>>> a, b
(0, [1, 2, 3, 4])
>>> *a, b = range(5)
>>> a, b
([0, 1, 2, 3], 4)
>>> a, *b, c = range(5)
>>> a, b, c
(0, [1, 2, 3], 4)

никогда раньше такого не видел, это очень мило!

mdeous 25.07.2010 22:01

какая версия? так как это не работает в 2.5.2

Dan D. 26.08.2010 19:14

работает с 3.1, но не с 2.7

Paweł Prażak 02.01.2011 22:09

Приятно - давно на это надеялся! Жаль, что разрушение пошло.

hbn 24.01.2011 00:47

Управление пределом рекурсии

Получение или установка максимальной глубины рекурсии с помощью sys.getrecursionlimit () и sys.setrecursionlimit ().

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

Умножение на логическое значение

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

class='<% isSelected ? "selected" : "" %>'

В Python вы можете умножить на логическое значение, и он сделает именно то, что вы ожидаете:

class='<% "selected" * isSelected %>'

Это связано с тем, что умножение приводит логическое значение к целому числу (0 для False, 1 для True), а в python умножение строки на int повторяет строки N раз.

+1, это хорошо. OTOH, поскольку это немного загадочно, легко понять, почему вы, возможно, не захотите этого делать из соображений удобочитаемости.

SingleNegationElimination 31.12.2009 02:38

Я бы написал bool(isSelected) и для надежности, и для удобочитаемости.

Marian 29.05.2010 15:46

вы также можете использовать что-то вроде: ('not-selected', 'selected')[isSelected], если вам также нужна опция для значения False ..

redShadow 19.07.2010 17:37

Правильный условные выражения был добавлен в Python в версии 2.5. Если вы используете версию 2.5+, вам, вероятно, не следует использовать эти уловки по причинам удобочитаемости.

Peter Graham 30.06.2011 06:12

Мод корректно работает с отрицательными числами

-1% 5 - это 4, как и должно быть, а не -1, как в других языках, таких как JavaScript. Это делает «витые окна» более чистыми в Python, вам просто нужно сделать следующее:

index = (index + increment) % WINDOW_SIZE

На большинстве языков number = coefficient x quotient + remainder. В Python (и Ruby) quotient отличается от JavaScript (или C или Java), потому что целочисленное деление в Python округляется до отрицательной бесконечности, а в JavaScript оно округляется до нуля (усекает). Я согласен с тем, что % в Python имеет больше смысла, но я не знаю, есть ли у /. См. en.wikipedia.org/wiki/Modulo_operation для получения подробной информации по каждому языку.

Mikel 24.01.2011 06:42

В общем, если abs (приращение) <WINDOW_SIZE, то вы можете сказать index = (index + WINDOW_SIZE + increment) на любом языке и заставить его делать правильные вещи.

George V. Reilly 29.01.2011 12:12

Вы можете построить функцию kwargs по запросу:

kwargs = {}
kwargs[str("%s__icontains" % field)] = some_value
some_function(**kwargs)

Вызов str () почему-то нужен, поскольку в противном случае python жалуется, что это не строка. Не знаю почему;) Я использую это для динамических фильтров в объектной модели Djangos:

result = model_class.objects.filter(**kwargs)

Причина жалоб заключается, вероятно, в том, что "field" является Unicode, что делает всю строку Unicode.

truppo 14.02.2010 01:30

Угадание целочисленной базы

>>> int('10', 0)
10
>>> int('0x10', 0)
16
>>> int('010', 0)  # does not work on Python 3.x
8
>>> int('0o10', 0)  # Python >=2.6 and Python 3.x
8
>>> int('0b10', 0)  # Python >=2.6 and Python 3.x
2

itertools

Этот модуль часто упускают из виду. В следующем примере используется itertools.chain() чтобы сгладить список:

>>> from itertools import *
>>> l = [[1, 2], [3, 4]]
>>> list(chain(*l))
[1, 2, 3, 4]

См. http://docs.python.org/library/itertools.html#recipes для дополнительных приложений.

Объекты Monkeypatching

Каждый объект в Python имеет член __dict__, в котором хранятся атрибуты объекта. Итак, вы можете сделать что-то вроде этого:

class Foo(object):
    def __init__(self, arg1, arg2, **kwargs):
        #do stuff with arg1 and arg2
        self.__dict__.update(kwargs)

f = Foo('arg1', 'arg2', bar=20, baz=10)
#now f is a Foo object with two extra attributes

Это можно использовать для произвольного добавления к объектам как атрибутов, так и функций. Это также можно использовать для создания быстроразвивающегося типа struct.

class struct(object):
    def __init__(**kwargs):
       self.__dict__.update(kwargs)

s = struct(foo=10, bar=11, baz = "i'm a string!')

кроме классов с __slots__

John La Rooy 10.02.2010 02:09

За исключением некоторых «примитивных» типов, реализованных на C (я думаю, из соображений производительности). Например, после a = 2 нет a.__dict__

Denilson Sá Maia 19.07.2010 03:43

Создание перечислений

В Python вы можете сделать это, чтобы быстро создать перечисление:

>>> FOO, BAR, BAZ = range(3)
>>> FOO
0

Но «перечисления» не обязательно должны иметь целочисленные значения. Вы даже можете сделать это:

class Colors(object):
    RED, GREEN, BLUE, YELLOW = (255,0,0), (0,255,0), (0,0,255), (0,255,255)

#now Colors.RED is a 3-tuple that returns the 24-bit 8bpp RGB 
#value for saturated red

Управление sys.modules

Вы можете напрямую управлять кешем модулей, делая модули доступными или недоступными по своему желанию:

>>> import sys
>>> import ham
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named ham

# Make the 'ham' module available -- as a non-module object even!
>>> sys.modules['ham'] = 'ham, eggs, saussages and spam.'
>>> import ham
>>> ham
'ham, eggs, saussages and spam.'

# Now remove it again.
>>> sys.modules['ham'] = None
>>> import ham
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named ham

Это работает даже для модулей, доступных находятся, и в некоторой степени для модулей, которые уже импортированы:

>>> import os
# Stop future imports of 'os'.
>>> sys.modules['os'] = None
>>> import os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named os
# Our old imported module is still available.
>>> os
<module 'os' from '/usr/lib/python2.5/os.pyc'>

Как показано в последней строке, изменение sys.modules влияет только на будущие операторы import, а не на прошлые, поэтому, если вы хотите повлиять на другие модули, важно внести эти изменения перед, вы даете им возможность попробовать и импортировать модули - так что раньше вы обычно импортируете их. None - это специальное значение в sys.modules, используемое для отрицательного кэширования (указывающее, что модуль не был найден в первый раз, поэтому нет смысла искать снова). Любое другое значение будет результатом операции import, даже если это не так. объект модуля. Вы можете использовать это для замены модулей объектами, которые ведут себя точно так, как вы хотите. Удаление записи из sys.modules приводит к тому, что следующий import выполняет обычный поиск модуля, даже если он уже был импортирован ранее.

И вы можете сделать sys.modules['my_module'] = MyClass(), чтобы реализовать «модуль» атрибутов только для чтения, если MyClass имеет правильные хуки.

warvariuc 04.03.2012 23:37

В Python нет секретов;)

Передача кортежа во встроенные функции

Многие функции Python принимают кортежи, что тоже не похоже. Например, вы хотите проверить, является ли ваша переменная числом, вы можете сделать:

if isinstance (number, float) or isinstance (number, int):  
   print "yaay"

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

if isinstance (number, (float, int)):  
   print "yaay"

круто, это вообще задокументировано?

Ponkadoodle 16.05.2010 11:10

Да, но об этом почти никто не знает.

evilpie 16.05.2010 16:35

Какие еще функции это поддерживают ?? Хороший совет

adamJLev 22.07.2010 20:14

Не уверен в других функциях, но это предполагается в статьях except (FooError, BarError).

Beni Cherniavsky-Paskin 22.01.2011 23:16

Вы можете присвоить несколько переменных одному и тому же значению

>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)

Полезно для компактной инициализации нескольких переменных значением None.

Вы также можете сделать: foo, bar, baz = [None] * 3, чтобы получить тот же результат.

Van Nguyen 17.07.2010 13:36

Вы также можете сравнить несколько вещей одновременно, например foo == bar == baz. По сути, это то же самое, что и главный ответ (который есть прямо сейчас).

asmeurer 28.12.2010 08:54

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

asmeurer 28.12.2010 08:56

threading.enumerate () предоставляет доступ ко всем объектам Thread в системе, а sys._current_frames () возвращает текущие кадры стека всех потоков в системе, поэтому объедините эти два, и вы получите дампы стека в стиле Java:

def dumpstacks(signal, frame):
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

Сделайте это в начале многопоточной программы на Python, и вы получите доступ к текущему состоянию потоков в любое время, отправив SIGQUIT. Вы также можете выбрать signal.SIGUSR1 или signal.SIGUSR2.

Видеть

Брекеты

def g():
    print 'hi!'

def f(): (
    g()
)

>>> f()
hi!

>>> def f (): (... g () ... g () Файл "<stdin>", строка 3 g () ^ SyntaxError: недопустимый синтаксис

bukzor 24.06.2010 05:24

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

bukzor 27.06.2010 20:46

Всем известно, что Python использует #{ и #} для фигурных скобок. Подлежит определенным лексическим ограничениям.

detly 14.07.2010 12:21

Совершенно секретные атрибуты

>>> class A(object): pass
>>> a = A()
>>> setattr(a, "can't touch this", 123)
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', "can't touch this"]
>>> a.can't touch this # duh
  File "<stdin>", line 1
    a.can't touch this
                     ^
SyntaxError: EOL while scanning string literal
>>> getattr(a, "can't touch this")
123
>>> setattr(a, "__class__.__name__", ":O")
>>> a.__class__.__name__
'A'
>>> getattr(a, "__class__.__name__")
':O'

АААА! Плохо, плохо, плохо!

asmeurer 28.12.2010 09:03

Хорошая обработка бесконечной рекурсии в словарях:

>>> a = {}
>>> b = {}
>>> a['b'] = b
>>> b['a'] = a
>>> print a
{'b': {'a': {...}}}

Это просто «хорошее обращение» с «печатью», оно не подразумевает хорошего обращения с языком.

haridsv 01.06.2010 23:59

И str(), и repr() возвращают строку, которую вы разместили выше. Однако оболочка ipython возвращает немного другое, более информативное: {'b': {'a': <Recursion on dict with id = 17830960>}}

Denilson Sá Maia 02.06.2010 06:21

@denilson: python использует модуль pprint, который доступен в стандартной оболочке python.

rafak 05.06.2010 23:49

+1 за первый, о котором я совершенно не имел ни малейшего представления.

asmeurer 28.12.2010 08:47

Множественные ссылки на итератор

Вы можете создать несколько ссылок на один и тот же итератор, используя умножение списка:

>>> i = (1,2,3,4,5,6,7,8,9,10) # or any iterable object
>>> iterators = [iter(i)] * 2
>>> iterators[0].next()
1
>>> iterators[1].next()
2
>>> iterators[0].next()
3

Это можно использовать для группировки итерируемого объекта в куски, например, как в этом примере из Документация itertools

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

Вы можете сделать обратное с itertools.tee - взять один итератор и вернуть n, который дает то же самое, но не разделяет состояние.

Daenyth 03.07.2010 08:41

На самом деле я не вижу разницы в этом: «a = iter (i)», а затем «b = a». Я также получаю несколько ссылок на один и тот же итератор - для меня в этом нет никакого волшебства, никаких скрытых особенность, что это просто обычный справочный материал для копирования языка. Что сделано, так это создание итератора, затем (умножение списка) копирование этого итератора несколько раз. Все, все на языке.

Juergen 03.07.2010 13:46

@Juergen: действительно, a = iter(i); b = a делает то же самое, и я мог бы записать это в ответ вместо [iter(i)] * n. В любом случае, никакого "волшебства" в этом нет. Это ничем не отличается от любого другого ответа на этот вопрос - ни один из них не является «волшебным», они все на языке. Что делает функции «скрытыми», так это то, что многие люди не осознают, что они возможны, или не осознают интересных способов их использования, пока на них не укажут явно.

David Z 04.07.2010 03:14

Ну, во-первых, вы можете сделать это произвольное количество раз с [iter(i)]*n. Кроме того, не обязательно хорошо известно (что опасно для многих), что list*int создает ссылочные, а не фактические копии элементов списка. Приятно видеть, что это действительно как-то полезно.

asmeurer 28.12.2010 08:38

Вы можете спросить любой объект, из какого модуля он пришел, посмотрев на его свойство __ module__. Это полезно, например, если вы экспериментируете с командной строкой и много чего импортировали.

Аналогичным образом вы можете спросить модуль, откуда он взялся, посмотрев на его свойство __ file__. Это полезно при отладке проблем с путями.

изменение итерации с использованием отрицательного шага

>>> s = "Hello World"
>>> s[::-1]
'dlroW olleH'
>>> a = (1,2,3,4,5,6)
>>> a[::-1]
(6, 5, 4, 3, 2, 1)
>>> a = [5,4,3,2,1]
>>> a[::-1]
[1, 2, 3, 4, 5]

Полезно знать, но второстепенный момент: это работает только с последовательностями, которые в целом не повторяются. То есть (n for n in (1,2,3,4,5))[::-1] не работает.

Don O'Donnell 15.07.2010 09:32

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

Denilson Sá Maia 04.08.2010 23:08

При использовании интерактивной оболочки "_" содержит значение последнего напечатанного элемента:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> _
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

Я всегда забываю об этом! Это отличная функция.

chimeracoder 23.07.2010 00:17

Автоматическая переменная _ - лучшая функция при использовании оболочки Python в качестве калькулятора. Кстати, очень мощный калькулятор.

Denilson Sá Maia 04.08.2010 23:03

Я все еще пытаюсь использовать %% в оболочке python из слишком большого количества Mathematica в предыдущей жизни ... Если бы только %% было допустимым именем переменной, я бы установил %% = _...

Conspicuous Compiler 15.11.2010 15:42

Это уже кто-то дал (не знаю, было ли это раньше, но проголосовали выше).

asmeurer 28.12.2010 08:39

__ для предпоследнего и ___ для предпоследнего

wim 19.07.2011 15:44

Срезы и изменчивость

Копирование списков

>>> x = [1,2,3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]

Замена списков

>>> x = [1,2,3]
>>> y = x
>>> y[:] = [4,5,6]
>>> x
[4, 5, 6]

Совместите распаковку с функцией печати:

# in 2.6 <= python < 3.0, 3.0 + the print function is native
from __future__ import print_function 

mylist = ['foo', 'bar', 'some other value', 1,2,3,4]  
print(*mylist)

Я предпочитаю что-то вроде print(' '.join([str(x) for x in mylist])). Использовать такую ​​распаковку слишком умно.

Brian 16.07.2010 22:49

С точки зрения производительности, я думаю, что «умная» версия быстрее (после проведения некоторых совершенно ненаучных тестов). Кроме того, вы знаете, что * означает, что вы распаковываете список или кортеж, и можете использовать ключевое слово sep.

Wayne Werner 16.07.2010 23:28

Я нахожу это простым и понятным, но мне всегда интересно, почему Пилинт настаивает на том, что в нем слишком много магии;)

Paweł Prażak 02.01.2011 22:26

@ Paweł Praak: Я считаю, что PyLint просто считает * и ** слишком волшебными, и точка.

ssokolow 05.09.2011 06:11

возможно, у некоторых людей просто аллергия на * и ** из-за сходства указателя и двойного указателя;)

Paweł Prażak 05.09.2011 10:55

@Brian Я бы отбросил список и использовал генератор print(' '.join(word for word in mylist))

Paweł Prażak 05.09.2011 11:03

Этот ответ был перенесен в сам вопрос по просьбе многих людей.

+1 за удивительность, время и преданность делу.

sqram 17.07.2010 02:16

Можно ли принять этот ответ или перенести его в вопрос? Было бы неплохо, чтобы такой индекс был наверху.

Denilson Sá Maia 24.09.2010 06:02

Из словаря python 3.1 (2.7) поддерживаются определения наборов:

{ a:a for a in range(10) }
{ a for a in range(10) }

не существует такой вещи, как понимание кортежей, и это не синтаксис для понимания dict.

SilentGhost 19.07.2010 01:31

Отредактировал опечатку с пониманием слов.

Piotr Duda 19.07.2010 01:58

ох, похоже, мне нужно обновить свою версию python, чтобы я мог играть с dict и устанавливать понимания

Carson Myers 19.07.2010 10:23

для словарей это лучше, но dict( (a,a) for a in range(10) ) тоже работает, и ваша ошибка, вероятно, связана с запоминанием этой формы

Dan D. 26.08.2010 19:22

Я не могу ждать использовать эту функцию.

asmeurer 28.12.2010 08:48

Python 2.x игнорирует запятые, если они находятся после последнего элемента последовательности:

>>> a_tuple_for_instance = (0,1,2,3,)
>>> another_tuple = (0,1,2,3)
>>> a_tuple_for_instance == another_tuple
True

Завершающая запятая приводит к тому, что одиночный элемент в скобках обрабатывается как последовательность:

>>> a_tuple_with_one_element = (8,)

Python3 также игнорирует их.

Alexander Artemenko 15.07.2011 14:56

** Using sets to reference contents in sets of frozensets**

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

>>> fabc = frozenset('abc')
>>> fxyz = frozenset('xyz')
>>> mset = set((fabc, fxyz))
>>> mset
{frozenset({'a', 'c', 'b'}), frozenset({'y', 'x', 'z'})}

Однако можно проверить членство и удалить / отбросить членов, используя обычные наборы:

>>> abc = set('abc')
>>> abc in mset
True
>>> mset.remove(abc)
>>> mset
{frozenset({'y', 'x', 'z'})}

Цитата из документов стандартной библиотеки Python:

Note, the elem argument to the __contains__(), remove(), and discard() methods may be a set. To support searching for an equivalent frozenset, the elem set is temporarily mutated during the search and then restored. During the search, the elem set should not be read or mutated since it does not have a meaningful value.

К сожалению, и, возможно, удивительно, то же самое нельзя сказать о словарях:

>>> mdict = {fabc:1, fxyz:2}
>>> fabc in mdict
True
>>> abc in mdict
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unhashable type: 'set'

Служебная функция textwrap.dedent в python может оказаться весьма полезной для проверки того, что возвращенная многострочная строка равна ожидаемому результату, не нарушая отступы ваших модульных тестов:

import unittest, textwrap

class XMLTests(unittest.TestCase):
    def test_returned_xml_value(self):
        returned_xml = call_to_function_that_returns_xml()
        expected_value = textwrap.dedent("""\
        <?xml version = "1.0" encoding = "utf-8"?>
        <root_node>
            <my_node>my_content</my_node>
        </root_node>
        """)

        self.assertEqual(expected_value, returned_xml)

Срезы как lvalues. Это Решето Эратосфена создает список, который имеет либо простое число, либо 0. Элементы обнуляются при назначении среза в цикле.

def eras(n):
    last = n + 1
    sieve = [0,0] + list(range(2, last))
    sqn = int(round(n ** 0.5))
    it = (i for i in xrange(2, sqn + 1) if sieve[i])
    for i in it:
        sieve[i*i:last:i] = [0] * (n//i - i + 1)
    return filter(None, sieve)

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

Лямбды с нулевым аргументом и с переменным аргументом

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

>>> f = lambda: 'foo'
>>> f()
'foo'

Они также могут принимать обычный синтаксис *args и **kwargs:

>>> g = lambda *args, **kwargs: args[0], kwargs['thing']
>>> g(1, 2, 3, thing='stuff')
(1, 'stuff')

Основная причина, по которой я хочу сохранить лямбду: defaultdict(lambda: 1).

eswald 09.10.2010 21:39

Многострочные струны

Один из подходов - использовать обратную косую черту:

>>> sql = "select * from some_table \
where id > 10"
>>> print sql
select * from some_table where id > 10

Другой вариант - использовать тройную кавычку:

>>> sql = """select * from some_table 
where id > 10"""
>>> print sql
select * from some_table where id > 10

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

Третье решение, которое я нашел недавно, - разделить строку на строки и заключить их в круглые скобки:

>>> sql = ("select * from some_table " # <-- no comma, whitespace at end
           "where id > 10 "
           "order by name") 
>>> print sql
select * from some_table where id > 10 order by name

обратите внимание, что между строками нет запятой (это не кортеж), и вы должны учитывать любые конечные / ведущие пробелы, которые должна иметь ваша строка. Между прочим, все они работают с заполнителями (например, "my name is %s" % name).

давно искали это

locojay 19.06.2011 03:09

Это хорошо при написании длинного кода в коде, сохраняя при этом небольшую длину строки!

Joël 27.10.2011 19:45

pow () также может эффективно вычислять (x ** y)% z.

Существует менее известный третий аргумент встроенной функции pow(), который позволяет вычислять xy по модулю z более эффективно, чем просто выполнение (x ** y) % z:

>>> x, y, z = 1234567890, 2345678901, 17
>>> pow(x, y, z)            # almost instantaneous
6

Для сравнения, (x ** y) % z не дал результата в течение одной минуты на моей машине при тех же значениях.

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

bukzor 30.07.2010 22:04

@buzkor: это тоже очень полезно для криптографии

Agos 31.07.2010 03:23

Помните, что это функция встроенныйpow(). Это нет, функция math.pow(), которая принимает только 2 аргумента.

Denilson Sá Maia 04.08.2010 22:59

Я помню, как категорически заявлял, что я не смогу кодировать криптографию на чистом Python без этой функции. Это было в 2003 году, поэтому версия Python, с которой я работал, была 2.2 или 2.3. Интересно, дурачился ли я, и тогда у pow был этот третий параметр или нет.

Omnifarious 21.08.2010 13:19

pow имел этот третий параметр, по крайней мере, начиная с Python 2.1. Однако, согласно документации, «[i] в ​​Python 2.1 и более ранних версиях pow() с тремя аргументами с плавающей запятой возвращал платформо-зависимые результаты в зависимости от случайностей округления с плавающей запятой».

Tamás 21.08.2010 18:05

Самое замечательное здесь то, что вы можете отвергать это поведение в своих собственных объектах, используя __pow__. Вам просто нужно определить необязательный третий аргумент. И для получения дополнительной информации о том, где это будет использоваться, см. en.wikipedia.org/wiki/Modular_exponentiation.

asmeurer 28.12.2010 08:30

Маленькая теорема Ферма сделана быстро!

ŹV - 26.01.2012 00:04

Обратные косые черты внутри необработанных строк по-прежнему могут избегать кавычек. Видеть это:

>>> print repr(r"aaa\"bbb")
'aaa\"bbb'

Обратите внимание, что в последней строке присутствуют как обратная косая черта, так и двойные кавычки.

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

>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\"'

Это происходит потому, что необработанные строки были реализованы для помощи в написании регулярных выражений, а не для записи путей Windows. Прочтите подробное обсуждение этого вопроса на Попался - обратная косая черта в именах файлов Windows.

Обратите внимание, что обратная косая черта является частью Все еще строки после этого ... Так что можно не рассматривать это как обычное экранирование.

huin 21.08.2010 11:18

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

asmeurer 28.12.2010 08:59

Или просто используйте (прямые) косые черты, так как Windows API будет переводить их автоматически, и тогда вы, наконец, можете забыть о путях в стиле DOS. (Хотя вы должен используете обратную косую черту для ресурсов стиля "\\ server \ share \ path \ file")

Terence Simpson 04.12.2011 12:45

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

>>> 'xyz' * 3
'xyzxyzxyz'

>>> [1, 2] * 3
[1, 2, 1, 2, 1, 2]

>>> (1, 2) * 3
(1, 2, 1, 2, 1, 2)

Тот же результат мы получаем с отраженными (переставленными) операндами

>>> 3 * 'xyz'
'xyzxyzxyz'

Это работает так:

>>> s = 'xyz'
>>> num = 3

Чтобы оценить выражение, интерпретатор s * номер вызывает s .___ mul ___ (число)

>>> s * num
'xyzxyzxyz'

>>> s.__mul__(num)
'xyzxyzxyz'

Чтобы оценить выражение, интерпретатор число * с вызывает число .___ муль ___ (s)

>>> num * s
'xyzxyzxyz'

>>> num.__mul__(s)
NotImplemented

Если вызов возвращает Не реализована, тогда интерпретатор вызывает отраженная операция s .___ rmul ___ (число), если операнды имеют разные типы

>>> s.__rmul__(num)
'xyzxyzxyz'

См. http://docs.python.org/reference/datamodel.html#object.rmul

+1 Я знал об умножении последовательностей, но отраженные операнды для меня в новинку.

Björn Pollex 12.09.2010 11:53

@Space, в конце концов, было бы непифонично иметь x * y != y * x :)

badp 12.09.2010 21:59

В python у вас май есть x * y! = Y * x (этого достаточно, чтобы поиграть с методами 'мул').

rob 13.09.2010 02:14

Увидев много вопросов о проблемах с x= [] * 20, я думаю, не было бы лучше делать мелкие копии операндов по умолчанию.

warvariuc 04.03.2012 23:23

перечислить с другим начальным индексом

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

Начиная с Python 2.6, вы можете указать начальный индекс enumerate во втором аргументе:

>>> l = ["spam", "ham", "eggs"]
>>> list(enumerate(l))
>>> [(0, "spam"), (1, "ham"), (2, "eggs")]
>>> list(enumerate(l, 1))
>>> [(1, "spam"), (2, "ham"), (3, "eggs")]

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

for ri, row in enumerate(matrix):
    for ci, column in enumerate(matrix[ri:], ri):
        # ci now refers to the proper column index

Как ни странно, такое поведение enumerate не задокументировано в help(enumerate), только в онлайн-документация.

help(enumerate) имеет правильную сигнатуру функции в python2.x, но не в py3k. Полагаю, нужно исправить ошибку.

SilentGhost 19.10.2010 14:10

help(enumerate) определенно ошибочен в Python 2.6.5. Возможно, они уже исправили это в Python 2.7.

Tamás 19.10.2010 14:35

help(enumerate) из Python 3.1.2 говорит перечислить класс (объект) | перечислить (итерируемый) -> итератор для индекса, значение итерируемого, но трюк из ответа работает нормально.

Cristian Ciupitu 19.10.2010 22:49

Похоже, это было добавлено в Python 2.6, так как в Python 2.5 это не работает.

Tamás 23.09.2011 13:35

Не «скрытый», но весьма полезный и редко используемый

Быстрое создание таких функций соединения строк

 comma_join = ",".join
 semi_join  = ";".join

 print comma_join(["foo","bar","baz"])
 'foo,bar,baz

и

Возможность создавать списки строк более элегантно, чем кавычки, запятые.

l = ["item1", "item2", "item3"]

заменен на

l = "item1 item2 item3".split()

Я думаю, что и то, и другое делают материал более длинным и запутанным.

XTL 16.02.2012 12:18

Я не знаю. Я нашел места, где разумное использование облегчало чтение.

Noufal Ibrahim 16.02.2012 15:55

Модель объектных данных

Вы можете переопределить оператор любой в языке для своих собственных классов. См. Полный список в эта страница. Некоторые примеры:

  • Вы можете изменить любой оператор (* + - / // % ^ == < > <= >= . и т. д.). Все это делается путем переопределения __mul__, __add__ и т. д. В ваших объектах. Вы даже можете переопределить такие вещи, как __rmul__, чтобы обрабатывать отдельно your_object*something_else и something_else*your_object. . - это доступ к атрибутам (a.b), который можно переопределить для обработки любого произвольного b с помощью __getattr__. Также сюда включен a(…) с использованием __call__.

  • Вы можете создать свой собственный синтаксис среза (a[stuff]), который может быть очень сложным и сильно отличаться от стандартного синтаксиса, используемого в списках (numpy имеет хороший пример силы этого в своих массивах), используя любую комбинацию ,, : и , который вам нравится, используя объекты Slice.

  • Обращайте особое внимание на то, что происходит со многими ключевыми словами в языке. Включены del, in, import и not.

  • Обработайте то, что происходит, когда с вашим объектом вызывается множество встроенных функций. Стандартные __int__, __str__ и т. д. Идут сюда, но также идут __len__, __reversed__, __abs__ и три аргумента __pow__ (для модульного возведения в степень).

Для in необходимо переопределить __contains__.

asmeurer 29.12.2010 00:20

распаковка кортежей в Python 3

в python 3 вы можете использовать синтаксис, идентичный необязательным аргументам в определении функции для распаковки кортежа:

>>> first,second,*rest = (1,2,3,4,5,6,7,8)
>>> first
1
>>> second
2
>>> rest
[3, 4, 5, 6, 7, 8]

но менее известная и более мощная функция позволяет вам иметь неизвестное количество элементов в середине списка:

>>> first,*rest,last = (1,2,3,4,5,6,7,8)
>>> first
1
>>> rest
[2, 3, 4, 5, 6, 7]
>>> last
8

Довольно аскетично :) крутой :)

pielgrzym 26.03.2011 14:27

мне нравится, облом не работает в 2.7 ..

wim 26.07.2011 07:59

вставить против добавления

не особенность, но может быть интересно

предположим, вы хотите вставить некоторые данные в список, а затем отменить его. самая легкая вещь

count = 10 ** 5
nums = []
for x in range(count):
    nums.append(x)
nums.reverse()

тогда вы думаете: а как насчет того, чтобы вместо этого вставить числа с начала? так:

count = 10 ** 5 
nums = [] 
for x in range(count):
    nums.insert(0, x)

но оказывается в 100 раз медленнее! если мы установим count = 10 ** 6, он будет в 1000 раз медленнее; это потому, что insert - O (n ^ 2), а append - O (n).

причина этой разницы в том, что insert должен перемещать каждый элемент в списке каждый раз, когда он вызывается; append просто добавьте в конец списка эти элементы (иногда приходится перераспределять все, но это все равно намного быстрее)

Или вы можете использовать nums.reverse () и сделать это ядром - без необходимости использовать range ()

rob 07.01.2011 19:53

я не понял твою точку зрения, извини ..

Ant 08.01.2011 14:43

Интересен факт реализации списков Python с помощью массивов; однако этот пример не так полезен, потому что идиоматический способ перевернуть список - это использовать обратный метод без каких-либо дополнительных шагов.

rob 09.01.2011 02:17

И поэтому существует collections.deque - вы можете вставлять и выталкивать записи с любого конца в O (1)

ncoghlan 01.02.2011 09:00

namedtuple - это кортеж

>>> node = namedtuple('node', "a b")
>>> node(1,2) + node(5,6)
(1, 2, 5, 6)
>>> (node(1,2), node(5,6))
(node(a=1, b=2), node(a=5, b=6))
>>> 

Еще несколько экспериментов для ответа на комментарии:

>>> from collections import namedtuple
>>> from operator import *
>>> mytuple = namedtuple('A', "a b")
>>> yourtuple = namedtuple('Z', "x y")
>>> mytuple(1,2) + yourtuple(5,6)
(1, 2, 5, 6)
>>> q = [mytuple(1,2), yourtuple(5,6)]
>>> q
[A(a=1, b=2), Z(x=5, y=6)]
>>> reduce(operator.__add__, q)
(1, 2, 5, 6)

Итак, namedtuple - это подтип интересно для tuple.

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

Samir Talwar 09.01.2011 04:01

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

Apalala 09.01.2011 04:25

@Apalala: Я предполагал это, но никогда не проверял. Вы правы: это интересная и скрытая особенность. Думаю, полезный - другое дело.

Samir Talwar 09.01.2011 19:34

Также интересно то, что вы можете передать результат вызова namedtuple непосредственно в определение класса, как в class rectangle(namedtuple("rectangle", "width height")):, чтобы добавить собственные методы.

Ben Blank 10.01.2011 22:29

@Samir Talwar Я использую namedtuple в качестве представления для деревьев синтаксического анализа, и их поведение было полезно при слиянии братьев и сестер, поэтому они больше походили на списки. Представьте себе типичные грамматические конструкции для списка ...

Apalala 11.01.2011 04:10

@ Апалала: Хорошо, ты меня продал. Не могу сказать, как я подхожу к проблеме, но эта функция явно полезна.

Samir Talwar 13.01.2011 02:24

@ Бен Бланк. Я не понял вашего комментария о том, как давать имена классам.

Apalala 13.01.2011 02:32

@Apalala - Вот пример: pastebin.com/d6e5VMgb

Ben Blank 13.01.2011 03:08

@ Бен Бланк. Невероятный! Это заслуживает отдельного ответа.

Apalala 14.01.2011 07:14

Модуль экспортирует ВСЕ в свое пространство имен

Включая имена, импортированные из других модулей!

# this is "answer42.py"
from operator import *
from inspect  import *

Теперь проверьте, что можно импортировать из модуля.

>>> import answer42
>>> answer42.__dict__.keys()
['gt', 'imul', 'ge', 'setslice', 'ArgInfo', 'getfile', 'isCallable', 'getsourcelines', 'CO_OPTIMIZED', 'le', 're', 'isgenerator', 'ArgSpec', 'imp', 'lt', 'delslice', 'BlockFinder', 'getargspec', 'currentframe', 'CO_NOFREE', 'namedtuple', 'rshift', 'string', 'getframeinfo', '__file__', 'strseq', 'iconcat', 'getmro', 'mod', 'getcallargs', 'isub', 'getouterframes', 'isdatadescriptor', 'modulesbyfile', 'setitem', 'truth', 'Attribute', 'div', 'CO_NESTED', 'ixor', 'getargvalues', 'ismemberdescriptor', 'getsource', 'isMappingType', 'eq', 'index', 'xor', 'sub', 'getcomments', 'neg', 'getslice', 'isframe', '__builtins__', 'abs', 'getmembers', 'mul', 'getclasstree', 'irepeat', 'is_', 'getitem', 'indexOf', 'Traceback', 'findsource', 'ModuleInfo', 'ipow', 'TPFLAGS_IS_ABSTRACT', 'or_', 'joinseq', 'is_not', 'itruediv', 'getsourcefile', 'dis', 'os', 'iand', 'countOf', 'getinnerframes', 'pow', 'pos', 'and_', 'lshift', '__name__', 'sequenceIncludes', 'isabstract', 'isbuiltin', 'invert', 'contains', 'add', 'isSequenceType', 'irshift', 'types', 'tokenize', 'isfunction', 'not_', 'istraceback', 'getmoduleinfo', 'isgeneratorfunction', 'getargs', 'CO_GENERATOR', 'cleandoc', 'classify_class_attrs', 'EndOfBlock', 'walktree', '__doc__', 'getmodule', 'isNumberType', 'ilshift', 'ismethod', 'ifloordiv', 'formatargvalues', 'indentsize', 'getmodulename', 'inv', 'Arguments', 'iscode', 'CO_NEWLOCALS', 'formatargspec', 'iadd', 'getlineno', 'imod', 'CO_VARKEYWORDS', 'ne', 'idiv', '__package__', 'CO_VARARGS', 'attrgetter', 'methodcaller', 'truediv', 'repeat', 'trace', 'isclass', 'ior', 'ismethoddescriptor', 'sys', 'isroutine', 'delitem', 'stack', 'concat', 'getdoc', 'getabsfile', 'ismodule', 'linecache', 'floordiv', 'isgetsetdescriptor', 'itemgetter', 'getblock']
>>> from answer42 import getmembers
>>> getmembers
<function getmembers at 0xb74b2924>
>>> 

Это хорошая причина не для from x import *, а для определения __all__ =.

Как это скрытая функция? __all__ существует для ограничения того, что экспортируется, и это даже в учебнике.

Cat Plus Plus 13.01.2011 03:34

@PiotrLegnica Знаете ли вы, что модуль экспортирует также то, что он импортирует, если не используется _все_? Это не похоже на большинство языков с модулями, и я не читал об этой «возможности» в документации, поэтому для меня она квалифицируется как скрытый.

Apalala 13.01.2011 04:05

@Apalala: почему не следует экспортировать импортированные (под) модули, учитывая тот факт, что они находятся в пространстве имен основного модуля?

Cristian Ciupitu 14.01.2011 05:44

@Cristian Ciuptu. В большинстве других языков модуль (или его эквивалент) экспортирует только то, что он определяет, плюс, неявно, то, что доступно из того, что он определяет. Это традиционно часть разделения задач и сокрытия реализации. Модуль может импортировать, скажем, math для выполнения своей задачи и справиться со стандартной арифметикой в ​​более поздних версиях; импортирующие модули не должны знать об этом (традиционно).

Apalala 14.01.2011 06:53

IOW, если вы хотите использовать math.sqrt(), вам следует импортировать его из math, а не из answer42.

Apalala 14.01.2011 07:59

@Apala: В первую очередь я понял вашу точку зрения относительно других языков, но, учитывая динамический характер Python и объектную ориентацию, такое поведение не вызывает удивления.

Cristian Ciupitu 15.01.2011 00:03

@Cristian Ciupitu. Это строго плохо документированный выбор дизайна, который не имеет ничего общего с динамикой языка. Это также настолько необычно, неожиданно и бесполезно, что может считаться недостатком дизайна.

Apalala 15.01.2011 07:18

@Apalala: чем модуль отличается от класса или, скажем, типа int или float? Все они являются объектами, и все они находятся в пространстве имен модуля. Дизайн выдержан. Это позволяет вам делать такие вещи, как def f(m, x): return m.sqrt(x); f(math, x), хотя это не совсем хороший стиль кодирования. Эта «особенность» необычна и неожиданна, только если вы сравните ее с другими языками (которые менее «динамичны», что бы это ни значило).

Cristian Ciupitu 16.01.2011 18:17

@Apalala: если вы хотите увидеть хороший вариант использования, ознакомьтесь с исходным кодом модуля os. Он делает такие вещи, как import posixpath as path или import ntpath as path, posixpath и ntpath, конечно же, другие модули.

Cristian Ciupitu 16.01.2011 18:23

@Cristian Ciupitu Я уступаю. Это полезно и постоянно используется. Но мне все еще не нравится, что это так недокументировано.

Apalala 18.01.2011 07:18

Операторы можно вызывать как функции:

from operator import add
print reduce(add, [1,2,3,4,5,6])

? как вы думаете, операторы?

Ant 23.01.2011 21:00

извините, я не поняла ... как вы думаете, что такое операторы?

Ant 23.01.2011 22:18

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

Brendon Crawford 25.01.2011 23:59

Простота:

>>> 'str' in 'string'
True
>>> 'no' in 'yes'
False
>>> 

это то, что мне нравится в Python, вместо этого я видел много не очень питонической идиомы:

if 'yes'.find("no") == -1:
    pass

Я не согласен с этим, потому что это несовместимо с поведением in в других типах последовательностей. 1 in [3, 2, 1] - это True, но [2, 1] in [3, 2, 1] - это False, и это действительно могло бы стать проблемой, если бы это был True. Но это то, что потребуется, чтобы привести его в соответствие с описанным здесь поведением строки. Поэтому я думаю, что подход .find() на самом деле более питонический, хотя, конечно, .find() должен был возвращать None вместо -1.

Kragen Javier Sitaker 12.01.2012 08:21

Также обратите внимание: 'str' не входит в 'abc' #true

Kosta 12.01.2012 13:31

Динамически добавляемые атрибуты

Это может быть полезно, если вы думаете о добавлении некоторых атрибутов в свои классы, просто вызывая их. Это можно сделать, переопределив функцию-член __getattribute__, которая вызывается при использовании операнда точка. Итак, давайте посмотрим, например, фиктивный класс:

class Dummy(object):
    def __getattribute__(self, name):
        f = lambda: 'Hello with %s'%name
        return f

Когда вы создаете экземпляр объекта-пустышки и выполняете вызов метода, вы получите следующее:

>>> d = Dummy()
>>> d.b()
'Hello with b'

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

У меня есть суть в github с этим простым кодом и его эквивалентом на Ruby, сделанным другом.

Заботиться!

Изменение метки функции во время выполнения:

>>> class foo:
...   def normal_call(self): print "normal_call"
...   def call(self): 
...     print "first_call"
...     self.call = self.normal_call

>>> y = foo()
>>> y.call()
first_call
>>> y.call()
normal_call
>>> y.call()
normal_call
...

Я не уверен, где (и есть ли) это в документах Python, но для python 2.x (по крайней мере, 2.5 и 2.6, которые я только что пробовал) оператор print можно вызывать с круглыми скобками. Это может быть полезно, если вы хотите иметь возможность легко переносить некоторый код Python 2.x на Python 3.x.

Пример: print('We want Moshiach Now') должен печатать We want Moshiach Now, работающий в python 2.5, 2.6 и 3.x.

Кроме того, оператор not можно вызывать с круглыми скобками в Python 2 и 3: not False и not(False) оба должны вернуть True.

Круглые скобки также могут работать с другими операторами и операторами.

РЕДАКТИРОВАТЬ: НЕ стоит ставить круглые скобки вокруг операторов not (и, вероятно, любых других операторов), поскольку это может привести к неожиданным ситуациям, подобным этой (это происходит потому, что круглые скобки на самом деле окружают 1):

>>> (not 1) == 9
False

>>> not(1) == 9
True

Это также может работать для некоторых значений (я думаю, что это недопустимое имя идентификатора), например: not'val' должен вернуть False, а print'We want Moshiach Now' должен вернуть We want Moshiach Now. (но not552 вызовет ошибку NameError, поскольку это действительное имя идентификатора).

Побочный эффект одного из основных правил проектирования синтаксиса Python. Скобки и пробелы можно изменять практически любым способом, что не делает их значение неоднозначным. (Вот почему вы получаете больше свободы при переносе слов, таких как операторы if / while, если вы помещаете тестовое тело в скобки.)

ssokolow 17.02.2011 08:55

То, что сказал ssokolow, правильно. В python 2.6 язык был обновлен, чтобы быть (более) совместимым с python 3. В python 3+ скобки необходимы для вызова print. см. здесь для получения дополнительной информации: docs.python.org/whatsnew/2.6.html#pep-3105-print-as-a-functi‌ в

Jake 17.02.2011 09:23

В Python есть «частные» переменные

Переменные, которые начинаются, но не заканчиваются двойным подчеркиванием, становятся закрытыми, и не только по соглашению. Фактически __var превращается в _Classname__var, где Classname - это класс, в котором была создана переменная. Они не передаются по наследству и не могут быть отменены.


>>> class A:
...     def __init__(self):
...             self.__var = 5
...     def getvar(self):
...             return self.__var
... 
>>> a = A()
>>> a.__var
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: A instance has no attribute '__var'
>>> a.getvar()
5
>>> dir(a)
['_A__var', '__doc__', '__init__', '__module__', 'getvar']
>>>

ммм ... не совсем "настоящие частные переменные". Вам ничего не мешает получить доступ к _A__var ...

Jake 23.02.2011 01:18

Ничто также не мешает вам получить доступ к частным ячейкам памяти в программах на C++ для работы с частными переменными, но это серьезно осуждается.

Benson 23.02.2011 04:43

В C++ это ограничение того, как язык обращается к памяти. Если вы хотите рискнуть привести к сбою вашей программы или побудить к этому кого-то, менее знакомого с кодом, этого нельзя предотвратить, не нарушив совместимость с языком C. «Изменение имени члена» Python не предназначено для использования в качестве механизма частных переменных. Он предназначен для публичных членов, которым необходимо отказаться от обычных правил наследования / переопределения. Назвать это «поддержкой частных переменных», потому что один популярный язык не может предложить полную изоляцию переменных, только обесценивает эту концепцию.

ssokolow 23.02.2011 05:26

Вы правы, я не подобрал хороших слов для описания функциональности - это не настоящие приватные переменные. Отредактировал как мог.

Ivan P 23.02.2011 19:31

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

Joschua 24.02.2011 18:00

В дополнение к этому, упомянутому ранее haridsv:

>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)

также можно сделать это:

>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)

Совсем не скрытая функция, но все же приятно:

import os.path as op

root_dir = op.abspath(op.join(op.dirname(__file__), ".."))

Сохраняет множество персонажей при манипулировании путями!

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

$ python -m http.server

... за которым следует $ wget http://<ipnumber>:8000/filename где-то еще.

Если вы все еще используете более старую (2.x) версию Python:

$ python -m SimpleHTTPServer

Вы также можете указать порт, например. python -m http.server 80 (поэтому вы можете опустить порт в URL-адресе, если у вас есть корень на стороне сервера)

Идентификатор Unicode в Python3:

>>> 'Unicode字符_تكوين_Variable'.isidentifier()
True
>>> Unicode字符_تكوين_Variable='Python3 rules!'
>>> Unicode字符_تكوين_Variable
'Python3 rules!'

Конечно, использование символов, отличных от ascii, в исходном коде Python по любой причине, кроме написания имен участников в документации по заголовку, является нарушением правил стиля кода pep-8.

SingleNegationElimination 28.07.2011 18:19

Умножьте строку, чтобы она повторилась

print "SO"*5 

дает

SOSOSOSOSO

Вы также можете сделать это со списками: [3]*3 == [3, 3, 3]

inspectorG4dget 26.05.2011 22:02

commands.getoutput

Если вы хотите получить вывод функции, которая выводится напрямую на stdout или stderr, как в случае с os.system, на помощь приходит commands.getoutput. Весь модуль просто потрясающий.

>>> print commands.getoutput('ls')
myFile1.txt    myFile2.txt    myFile3.txt    myFile4.txt    myFile5.txt
myFile6.txt    myFile7.txt    myFile8.txt    myFile9.txt    myFile10.txt
myFile11.txt   myFile12.txt   myFile13.txt   myFile14.txt   module.py

Учитывая, что это в основном предшественник модуля subprocess только для UNIX и был удален в Python 3.0, разве вы не должны говорить о subprocess вместо commands?

ssokolow 27.05.2011 04:47

Туш! Однако я использую 2.7 для Windows (не только для UNIX) на работе. Это работает здесь, и я только что обнаружил это. Таким образом, я подумал, что об этом стоит упомянуть.

inspectorG4dget 27.05.2011 17:46

в частности, subprocess.check_output

wim 19.01.2012 05:10

Когда-либо использовали xrange (INT) вместо range (INT) .... Он использует меньше памяти и не зависит от размера целого числа. Ура !! Разве это не хорошо?

В Python 3 оба они одинаковы.

Wok 27.05.2011 21:12

getattr принимает третий параметр

getattr(obj, attribute_name, default) похож на:

try:
    return obj.attribute
except AttributeError:
    return default

за исключением того, что attribute_name может быть любой строкой.

Это может быть действительно полезно для утка печатать. Может у вас есть что-то вроде:

class MyThing:
    pass
class MyOtherThing:
    pass
if isinstance(obj, (MyThing, MyOtherThing)):
    process(obj)

(кстати, isinstance(obj, (a,b)) означает isinstance(obj, a) or isinstance(obj, b).)

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

class MyThing:
    processable = True
class MyOtherThing:
    processable = True
if getattr(obj, 'processable', False):
    process(obj)

Добавьте наследование, и оно станет еще лучше: все ваши примеры обрабатываемых объектов могут наследовать от

class Processable:
    processable = True

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

mapreduce с использованием функций map и reduce

создать простой продукт следующим образом:

def sumprod(x,y):
    return reduce(lambda a,b:a+b, map(lambda a, b: a*b,x,y))

пример:

In [2]: sumprod([1,2,3],[4,5,6])
Out[2]: 32

Простой встроенный инструмент для тестирования производительности

Стандартная библиотека Python поставляется с очень простым в использовании модулем тестирования производительности под названием «timeit». Вы даже можете использовать его из командной строки, чтобы увидеть, какая из нескольких языковых конструкций самая быстрая.

Например.,

% python -m timeit 'r = range(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 48.4 usec per loop

% python -m timeit 'r = xrange(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 37.4 usec per loop

бесконечная рекурсия в списке

>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[2]
[1, 2, [...]]
>>> a[2][2][2][2][2][2][2][2][2] == a
True

я не думаю, что это особенность Python. ни это скрыто. где это можно использовать?

warvariuc 30.06.2011 12:31

в то время как не очень питонический, вы можете записать в файл с помощью print

print>>outFile, 'I am Being Written'

Объяснение:

This form is sometimes referred to as “print chevron.” In this form, the first expression after the >> must evaluate to a “file-like” object, specifically an object that has a write() method as described above. With this extended form, the subsequent expressions are printed to this file object. If the first expression evaluates to None, then sys.stdout is used as the file for output.

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

matchew 30.06.2011 18:08

Этот синтаксис был обновлен в Python 3, поэтому теперь вы можете использовать print('I am being writtten', file=outFile). Я как раз читал про перемены. Так что теперь он стал намного более питоническим.

shadowland 25.10.2011 21:28

очень хорошо. В последнее время я наслаждаюсь pypy, что может только задержать мой переход на python3.

matchew 25.10.2011 22:36

Кодировки string-escape и unicode-escape

Допустим, у вас есть строка из внешнего источника, содержащая \n, \t и так далее. Как преобразовать их в новую строку или вкладку? Просто декодируйте строку, используя кодировку string-escape!

>>> print s
Hello\nStack\toverflow
>>> print s.decode('string-escape')
Hello
Stack   overflow

Другая проблема. У вас есть обычная строка с литералами Unicode, такими как \u01245. Как заставить работать? Просто декодируйте строку, используя кодировку unicode-escape!

>>> s = '\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!'
>>> print s
\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!
>>> print unicode(s)
\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!
>>> print unicode(s, 'unicode-escape')
Привіт, світ!

Сглаживание list с помощью sum().

Встроенная функция sum() может использоваться для __add__list вместе, обеспечивая удобный способ сгладить list для list:

Python 2.7.1 (r271:86832, May 27 2011, 21:41:45) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> l = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Образец Борга

Это убийца из Алекс Мартелли. Все экземпляры Borg имеют общее состояние. Это устраняет необходимость использования одноэлементного шаблона (экземпляры не имеют значения, когда состояние является общим) и является довольно элегантным (но более сложным с новыми классами).

Значение foo можно переназначить в любом случае, и все будет обновлено, вы даже можете переназначить весь dict. Борг - идеальное имя, подробнее здесь.

class Borg:
    __shared_state = {'foo': 'bar'}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # rest of your class here

Это идеально подходит для совместного использования eventlet.GreenPool для управления параллелизмом.

чтобы активировать автозаполнение в IDE, которая его принимает (например, IDLE, Editra, IEP), вместо того, чтобы делать: "Здравствуй". (а затем вы нажимаете TAB), вы можете обмануть в IDE, просто сделайте привет ". (и вы нажимаете клавишу TAB) (как вы можете видеть, в начале нет одинарной кавычки), потому что он будет следовать только за последней пунктуацией, это похоже на то, когда вы добавляете: и нажимаете Enter, он добавляет непосредственно отступ, не знаю, внесет ли он изменения, но это не подсказка :)

Может кто-нибудь пояснить, что это значит?

the Tin Man 29.07.2011 05:50

что, когда вы нажимаете вкладку, выбор может быть доступен, даже если это не строка, просто сделайте это, например, IEP: ". и нажмите TAB, вы получите варианты, которые предлагают их при работе со строками ... или сделайте этот другой намек :: и нажмите Enter, вы получите идентификацию :)

Abdelouahab 30.07.2011 02:11

Похоже, это всего лишь одна или две функции обычного редактора.

XTL 16.02.2012 14:31

Вот 2 пасхальных яйца:


Один в самом питоне:

>>> import __hello__
Hello world...

И еще один в модуле Werkzeug, который немного сложно выявить, вот он:

Глядя на исходный код Werkzeug, в werkzeug/__init__.py есть строка, которая должна привлечь ваше внимание:

'werkzeug._internal':   ['_easteregg']

Если вам немного любопытно, это должно побудить вас взглянуть на werkzeug/_internal.py, там вы найдете функцию _easteregg(), которая принимает в качестве аргумента приложение wsgi, она также содержит некоторые данные в кодировке base64 и 2 вложенные функции, которые кажется, что делает что-то особенное, если в строке запроса находится аргумент с именем macgybarchakku.

Итак, чтобы раскрыть это пасхальное яйцо, похоже, вам нужно обернуть приложение функцией _easteregg(), давайте:

from werkzeug import Request, Response, run_simple
from werkzeug import _easteregg

@Request.application
def application(request):
    return Response('Hello World!')

run_simple('localhost', 8080, _easteregg(application))

Теперь, если вы запустите приложение и посетите http: // локальный: 8080 /? macgybarchakku, вы должны увидеть пасхальное яйцо.

Вот полезная функция, которую я использую при отладке ошибок типа

def typePrint(object):
    print(str(object) + " - (" + str(type(object)) + ")")

Он просто печатает ввод, за которым следует тип, например

>>> a = 101
>>> typePrint(a)
    101 - (<type 'int'>)

for line in open('foo'):
    print(line)

что эквивалентно (но лучше):

f = open('foo', 'r')
for line in f.readlines():
   print(line)
f.close()

Это совсем не эквивалент, потому что вы не можете предсказать, когда файл будет закрыт. Это зависит от переводчика. Насколько мне известно, мусор CPython собирает объекты как можно быстрее, но другие интерпретаторы могут этого не делать.

Cristian Ciupitu 07.10.2011 05:50

Печатать многострочные строки по одному за раз

Не очень полезная функция, скрытая в классе site._Printer, экземпляром которого является объект license. Последний при вызове распечатывает лицензию Python. Можно создать другой объект того же типа, передав строку - например, содержимое файла - в качестве второго аргумента и назовите его:

type(license)(0,open('textfile.txt').read(),0)()

Это будет печатать содержимое файла, разделенное на определенное количество строк за раз:

...
file row 21
file row 22
file row 23

Hit Return for more, or q (and Return) to quit:

Интерактивная отладка скриптов (и строк документации)

Я не думаю, что это так широко известно, как могло бы быть, но добавьте эту строку в любой скрипт python:

import pdb; pdb.set_trace()

вызовет появление отладчика PDB с курсором выполнения в этой точке кода. Что еще менее известно, я думаю, это то, что вы можете использовать ту же строку в doctest:

"""
>>> 1 in (1,2,3)   
Becomes
>>> import pdb; pdb.set_trace(); 1 in (1,2,3)
"""

Затем вы можете использовать отладчик для проверки среды тестирования. Вы не можете пройти через doctest, потому что каждая строка запускается автономно, но это отличный инструмент для отладки doctest globs и окружения.

В Python 2 вы можете сгенерировать строковое представление выражения, заключив его в обратные кавычки:

 >>> `sorted`
'<built-in function sorted>'

Этого нет в python 3.X.

Не функция программирования, но полезна при использовании Python с bash или shell scripts.

python -c"import os; print(os.getcwd());"

См. документация python здесь. Дополнительные моменты, на которые следует обратить внимание при написании более длинные скрипты Python, можно увидеть в это обсуждение.

У Python есть исключения для очень неожиданных вещей:

Импорт

Это позволит вам импортировать альтернативу, если библиотека отсутствует.

try:
    import json
except ImportError:
    import simplejson as json

Итерация

Для циклов сделайте это внутренне и перехватите StopIteration:

iter([]).next()
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    iter(a).next()
StopIteration

Утверждение

>>> try:
...     assert []
... except AssertionError:
...     print "This list should not be empty"
This list should not be empty

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

Целые числа округления: В Python есть функция round, которая возвращает числа типа double:

 >>> print round(1123.456789, 4)
1123.4568
 >>> print round(1123.456789, 2)
1123.46
 >>> print round(1123.456789, 0)
1123.0

У этой функции есть чудесное волшебное свойство:

 >>> print round(1123.456789, -1)
1120.0
 >>> print round(1123.456789, -2)
1100.0

Если вам нужно целое число в результате, используйте int для преобразования типа:

 >>> print int(round(1123.456789, -2))
1100
 >>> print int(round(8359980, -2))
8360000

Спасибо Грегор.

некоторые интересные функции с сокращением и оператором.

>>> from operator import add,mul
>>> reduce(add,[1,2,3,4])
10
>>> reduce(mul,[1,2,3,4])
24
>>> reduce(add,[[1,2,3,4],[1,2,3,4]])
[1, 2, 3, 4, 1, 2, 3, 4]
>>> reduce(add,(1,2,3,4))
10
>>> reduce(mul,(1,2,3,4))
24

Позиционные расширения и расширения ключевых слов Python можно использовать «на лету», а не только из сохраненного списка.

l=lambda x,y,z:x+y+z
a=1,2,3
print l(*a)
print l(*[a[0],2,3])

Обычно это более полезно с такими вещами:

a=[2,3]
l(*(a+[3]))

Диктограммы

>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Документация Python

Запись в Википедии

Установить понимание

>>> {i**2 for i in range(5)}                                                       
set([0, 1, 4, 16, 9])

Документация Python

Запись в Википедии

Это уже описано в stackoverflow.com/a/224747/497043.

Chris Morgan 16.02.2012 14:25

Не совсем скрытая функция, но то, что может пригодиться.

для просмотра элементов в списке попарно

for x, y in zip(s, s[1:]):

>>> float('infinity')
inf
>>> float('NaN')
nan

Больше информации:

Люди слишком часто об этом забывают. Я видел такие вещи, как наличие аргумента "count" для функции, который затем уменьшается на единицу, пока не дойдет до нуля, по умолчанию используется специальное значение, которое означает, что не нужно останавливаться, когда float('inf') будет хорошо работать, не требуя любой специальный код вообще (inf - 1 == inf).

Chris Morgan 16.02.2012 14:19

Другие вопросы по теме