Скрытые особенности Python
1420 jelovirt [2008-09-19 14:50:00]
Каковы менее известные, но полезные функции языка программирования Python?
- Попробуйте ограничить ответы на ядро Python.
- Одна функция для каждого ответа.
- Приведите пример и краткое описание функции, а не ссылку на документацию.
- Пометьте эту функцию, используя заголовок в качестве первой строки.
Быстрые ссылки на ответы:
- Распаковка аргументов
- Подтяжки
- Операторы сравнения цепочек
- Декораторы
- Default Argument Gotchas/Danger of Mutable Default arguments
- Дескрипторы
- Словарь по умолчанию
.get
значение - Тесты Docstring
- Синтаксис разрезания эллипсиса
- Перечисление
- Для /else
- Функция как аргумент iter()
- Генераторные выражения
-
import this
- Поменять местами значение
- Список шагов
-
__missing__
элементы - Многострочное регулярное выражение
- Именованное форматирование строк
- Вложенные представления в список/генераторы
- Новые типы во время выполнения
-
.pth
файлы - Кодирование ROT13
- Отладка регулярных выражений
- Отправка на генераторы
- Завершение вкладки в интерактивном интерпретаторе
- Тройное выражение
-
try/except/else
- Распаковка +
print()
функция -
with
утверждение
python hidden-features
191 ответ
741 Thomas Wouters [2008-09-19 16:47:00]
Операторы сравнения цепочек:
>>> 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
, но с меньшим количеством ввода и каждый термин оценивается только один раз.
512 BatchyX [2008-09-27 16:18:00]
Получить дерево разбора python regex для отладки вашего регулярного выражения.
Регулярные выражения - отличная функция python, но отладка их может быть больной, и слишком легко получить неправильное выражение.
К счастью, python может печатать дерево синтаксического анализа regex, передавая недокументированный экспериментальный скрытый флаг 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)
460 Dave [2008-09-22 22:51:00]
перечисление
Оберните итерируемый с перечислением, и он даст элемент вместе со своим индексом.
Например:
>>> 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
>>>
Литература:
419 freespace [2008-09-19 14:59: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 в конец генератора, в основном реплицируя вложенные для циклов:
>>> 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)
353 mbac32768 [2008-09-19 17:20:00]
iter() может принимать аргумент
Например:
def seek_next_line(f):
for c in iter(lambda: f.read(1),'\n'):
pass
Функция iter(callable, until_value)
повторно вызывает callable
и возвращает ее результат до тех пор, пока until_value
не будет возвращен.
339 Jason Baker [2008-09-22 07:34:00]
Будьте осторожны с изменяемыми аргументами по умолчанию
>>> 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]
317 Rafał Dowgird [2008-09-19 16:18:00]
Отправка значений в функции генератора. Например, имея эту функцию:
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
314 eduffy [2008-09-22 01:01:00]
Если вам не нравится использовать пробелы для обозначения областей, вы можете использовать C-style {}, выпустив:
from __future__ import braces
305 Rafał Dowgird [2008-09-19 16:33:00]
Аргумент шага в операторах среза. Например:
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]
290 DzinX [2008-09-19 15:32:00]
Декораторы
Decorators позволяют обернуть функцию или метод в другую функцию, которая может добавить функциональность, изменить аргументы или результаты и т.д. Вы пишете декораторов на одну строку над определением функции, начиная с знака "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
288 rlerallut [2008-09-22 14:55:00]
Синтаксис 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")
258 Armin Ronacher [2008-09-22 00:54:00]
Начиная с 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
имеется также подкласс подкласса defaultdict
, который выполняет почти то же самое, но вызывает функцию без аргументов для не существующих элементов:
>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}
Я рекомендую преобразовать такие dicts в обычные dicts, прежде чем передавать их функциям, которые не ожидают таких подклассов. Много кода использует d[a_key]
и ловит KeyErrors, чтобы проверить, существует ли элемент, который добавит новый элемент в dict.
247 Lucas S. [2008-09-19 17:00:00]
Обмен местами на месте
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
Правая часть присваивания - это выражение, которое создает новый кортеж. Левая часть задания сразу же распаковывает этот (не привязанный) кортеж к именам a
и b
.
После назначения новый кортеж не отображается и помечен для сбора мусора, а значения, привязанные к a
и b
, были заменены.
Как отмечено в разделе Python, посвященном структурам данных,
Обратите внимание, что множественное назначение на самом деле представляет собой комбинацию упаковки кортежей и распаковки последовательностей.
235 MvdD [2008-09-19 15:44:00]
Считываемые регулярные выражения
В 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})$"
222 e-satis [2008-09-21 18:00:00]
Распаковка аргументов функции
Вы можете распаковать список или словарь в качестве аргументов функции, используя *
и **
.
Например:
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)
Очень полезный ярлык, поскольку списки, кортежи и дикты широко используются в качестве контейнеров.
205 André [2009-06-21 23:32:00]
ROT13 является допустимым кодированием исходного кода, когда вы используете правильное объявление кодирования в верхней части файла кода:
#!/usr/bin/env python
# -*- coding: rot13 -*-
cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
183 Torsten Marek [2008-09-20 17:25:00]
Создание новых типов в полностью динамическом режиме
>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"
что точно совпадает с
>>> class NewType(object):
>>> x = "hello"
>>> n = NewType()
>>> n.x
"hello"
Возможно, это не самая полезная вещь, но приятно знать.
Изменить. Исправлено имя нового типа, должно быть NewType
- это то же самое, что и с оператором class
.
Изменить. Скорректировано название, чтобы более точно описать эту функцию.
179 Ycros [2008-09-20 23:06:00]
Контекстные менеджеры и оператор < <20 >
Представлено в PEP 343, контекстный менеджер - это объект, который действует как контекст времени выполнения для набора операторов.
Поскольку функция использует новые ключевые слова, она вводится постепенно: она доступна в Python 2.5 с помощью директивы __future__
. Python 2.6 и выше (включая Python 3) доступны по умолчанию.
Я использовал "with" statement много, потому что я считаю это очень полезной конструкцией, вот небольшая демонстрация:
from __future__ import with_statement
with open('foo.txt', 'w') as f:
f.write('hello!')
Что происходит здесь за кулисами, заключается в том, что "with" statement вызывает специальные методы __enter__
и __exit__
на файловый объект. Сведения об исключении также передаются в __exit__
, если какое-либо исключение было поднято из тела оператора with, что позволяет там обрабатывать исключения.
Что это для вас в этом конкретном случае, так это то, что он гарантирует, что файл будет закрыт, когда выполнение выходит из области набора with
, независимо от того, происходит ли это нормально или генерируется ли исключение. Это в основном способ абстрагирования общего кода обработки исключений.
Другие распространенные случаи использования включают блокировку потоков и транзакций базы данных.
168 Rory [2008-09-21 23:18:00]
Словари имеют метод get()
Словари имеют метод get(). Если вы делаете d ['key'], а ключ отсутствует, вы получаете исключение. Если вы выполните d.get( "ключ" ), вы вернетесь в None, если "ключ" не существует. Вы можете добавить второй аргумент, чтобы вернуть этот элемент вместо None, например: d.get('key', 0).
Это отлично подходит для таких вещей, как добавление номеров:
sum[value] = sum.get(value, 0) + 1
152 Nick Johnson [2008-09-19 17:04:00]
дескрипторы
Они - волшебство целого ряда основных функций 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, таковы, как они есть.
Раймонд Хеттингер отличный учебник, который намного лучше описывает их, чем я.
142 tghw [2008-09-22 21:08:00]
Условное присвоение
x = 3 if (y == 1) else 2
Он делает именно то, что это звучит: "присвойте 3 x, если y равно 1, иначе назначьте 2 x". Обратите внимание, что parens не нужны, но мне они нравятся для удобочитаемости. Вы также можете связать его, если у вас есть что-то более сложное:
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 - два класса.
141 Pierre-Jean Coudert [2008-09-19 17:04:00]
Doctest: документация и модульное тестирование в то же время.
Пример, извлеченный из документации 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()
138 Pasi Savolainen [2008-09-22 07:23:00]
Именованное форматирование
% -formatting принимает словарь (также применяется валидация% 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))
132 dgrant [2008-09-22 11:43:00]
Чтобы добавить больше модулей python (особенно сторонних), большинство людей, похоже, используют переменные среды PYTHONPATH или добавляют символические ссылки или каталоги в свои каталоги пакетов сайтов. Другой способ - использовать файлы *.pth. Здесь официальное описание python doc:
"Самый удобный способ [изменить путь поиска python] - добавить путь файл конфигурации в каталог что уже на пути Python, обычно к... /site -packages/ каталог. Файлы конфигурации пути имеют расширение .pth, и каждый строка должна содержать один путь, который будет добавлен к sys.path. (Потому как новые пути добавляются к sys.path, модули в добавленном каталоги не будут отменять стандартные модули. Это означает, что вы не можете использовать это механизм установки фиксированного версии стандартных модулей.)"
122 Constantin [2008-09-22 13:31:00]
Исключение else:
try:
put_4000000000_volts_through_it(parrot)
except Voom:
print "'E pining!"
else:
print "This parrot is no more!"
finally:
end_sketch()
Использование предложения else лучше, чем добавление дополнительного кода в предложение try, поскольку оно позволяет избежать случайного обнаружения исключения, которое не было вызвано защищенным кодом инструкцией try... except.
114 Thomas Wouters [2008-09-19 16:56:00]
Исключения для повторного создания:
# 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 с модулем "traceback".
106 cleg [2008-09-19 14:53:00]
Основные сообщения:)
import this
# btw look at this module source :)
Дзен Питона, Тим Петерс
Красивая лучше, чем уродливая.
Явный лучше, чем неявный.
Простой лучше, чем сложный.
Комплекс лучше, чем сложный.
Плоский лучше, чем вложенный.
Редкий лучше, чем плотный. Показатели удобочитаемости.
Особые случаи не являются достаточно сложными, чтобы нарушать правила.
Хотя практичность превосходит чистоту.
Ошибки никогда не должны проходить молча.
Если явно не отключен.
Перед лицом двусмысленности откажитесь от соблазна угадать. Должен быть один - и желательно только один - простой способ сделать это.
Хотя этот путь может быть не очевидным, если вы не голландский. Теперь лучше, чем никогда. Хотя никогда не бывает лучше, чем сейчас. Если внедрение трудно объяснить, это плохая идея.
Если внедрение легко объяснить, это может быть хорошей идеей.
Пространства имен - одна хорошая идея - пусть больше таких!
105 mjard [2008-10-03 21:38:00]
Завершение интерактивной переписки переводчика
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.
91 Kiv [2009-01-01 19:05:00]
Перегрузка оператора для встроенного 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}
Подробнее из стандартной ссылки на библиотеку: Установить типы
91 Rafał Dowgird [2008-09-19 15:45:00]
Вложенные списки и выражения генератора:
[(i,j) for i in range(3) for j in range(i) ]
((i,j) for i in range(4) for j in range(i) )
Они могут заменить огромные куски кода вложенного цикла.
85 Abgan [2008-12-17 11:09:00]
Отрицательный раунд
Функция round()
округляет число с плавающей точкой до заданной точности в десятичных разрядах, но точность может быть отрицательной:
>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'
Примечание: round()
всегда возвращает float, str()
, используемый в приведенном выше примере, потому что математика с плавающей запятой неточна, а под 2.x второй пример может печататься как 1234.5700000000001
. Также см. decimal
.
81 jpsimons [2009-12-06 00:50:00]
Умножение на булевское
Одна вещь, которую я постоянно делаю в веб-разработке, - это необязательная печать параметров HTML. Мы все видели такой код на других языках:
class='<% isSelected ? "selected" : "" %>'
В Python вы можете умножить на логическое значение, и он делает именно то, что вы ожидаете:
class='<% "selected" * isSelected %>'
Это связано с тем, что умножение приводит к булевому отношению к целому числу (0 для False, 1 для True), а в питоне, умножающем строку на int, повторяется строка N раз.
74 Armin Ronacher [2008-09-22 01:07:00]
Операция расширенного среза Python имеет едва известный элемент синтаксиса, многоточие:
>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)
К сожалению, это едва полезно, поскольку многоточие поддерживается только в том случае, если задействованы кортежи.
72 Scott Kirkwood [2009-04-29 23:56:00]
re может вызывать функции!
Тот факт, что вы можете вызывать функцию каждый раз, когда что-то соответствует регулярному выражению, очень удобен. Здесь у меня есть образец замены каждого "Hello" на "Hi" и "there" с помощью "Fred" и т.д.
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?'
70 Adrien Plisson [2011-01-05 12:29:00]
распаковка кортежей в 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
67 sa125 [2010-07-27 14:07:00]
Многострочные строки
Один подход заключается в использовании обратных косых черт:
>>> 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
).
63 Wayne Werner [2010-07-16 22:18:00]
Этот ответ был перемещен в вопрос сам по просьбе многих людей.
59 Tzury Bar Yochay [2008-09-22 21:22:00]
- Подчеркнутый символ содержит последнее значение вывода, отображаемое интерпретатором (в интерактивном сеансе):
>>> (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
56 Tamás [2010-07-30 15:36:00]
pow() также может эффективно вычислять (x ** y)% z.
Существует менее известный третий аргумент встроенной функции pow()
, которая позволяет более эффективно вычислять x y по модулю z, чем просто делать (x ** y) % z
:
>>> x, y, z = 1234567890, 2345678901, 17
>>> pow(x, y, z) # almost instantaneous
6
Для сравнения, (x ** y) % z
не дал результата за одну минуту на моей машине для тех же значений.
52 FA. [2008-11-29 02:27:00]
Вы можете легко транспонировать массив с zip.
a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]
52 Tamás [2010-10-19 12:53:00]
перечислять с другим начальным индексом
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)
, только в онлайн-документации.
50 jfs [2008-09-19 16:43:00]
Вы можете использовать property, чтобы сделать ваши интерфейсы классов более строгими.
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
Чтобы узнать больше о том, как работает свойство, обратитесь к дескрипторы.
48 lacker [2008-09-22 20:32:00]
Многие люди не знают о функции "dir". Это отличный способ выяснить, что объект может сделать из интерпретатора. Например, если вы хотите увидеть список всех строковых методов:
>>> dir("foo")
['__add__', '__class__', '__contains__', (snipped a bunch), 'title',
'translate', 'upper', 'zfill']
И если вам нужна дополнительная информация о конкретном методе, вы можете вызвать "help" на нем.
>>> help("foo".upper)
Help on built-in function upper:
upper(...)
S.upper() -> string
Return a copy of the string S converted to uppercase.
47 monkut [2008-10-22 10:24:00]
Вероятно, легко упущенный встроенный 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}
46 spiv [2008-09-27 16:37:00]
Встроенные кодеки 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'
43 James Brady [2008-12-26 19:05:00]
Интерпретатор в интерпретаторе
В стандартной библиотеке code вы можете включить свой собственный цикл чтения-eval-print внутри программы или запустить целую вложенную переводчик. Например. (скопировал мой пример из здесь)
$ 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 использует это с большим успехом благодаря наличию веб-консоли, из которой вы можете запросить состояние своего веб-приложения.
>>> 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]
не очень скрытая функция, но частичная чрезвычайно полезна для поздней оценки функций.
вы можете связать столько или несколько параметров в первоначальном вызове с частичным, как вы хотите, и вызвать его с любыми оставшимися параметрами позже (в этом примере я привязал аргумент begin/end args к диапазону, но назовите его второй раз с шагом arg)
Смотрите документацию.
36 utku_karatas [2008-11-04 16:09:00]
При отладке сложных структур данных модуль 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']
34 Constantin [2008-10-05 12:51:00]
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"
dict принимает аргументы ключевого слова:
>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}
29 Ruslan Spivak [2010-09-12 08:11:00]
Умножение последовательности и отраженные операнды
>>> '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 * num, вызовы интерпретатора s.___ mul ___ (num)
>>> s * num
'xyzxyzxyz'
>>> s.__mul__(num)
'xyzxyzxyz'
Для вычисления выражения num > s вызовы интерпретатора num.___ mul ___ (s)
>>> num * s
'xyzxyzxyz'
>>> num.__mul__(s)
NotImplemented
Если вызов возвращает NotImplemented, то вызовы интерпретатора отраженная операция s.___ rmul ___ (num), если операнды имеют разные типы
>>> s.__rmul__(num)
'xyzxyzxyz'
См. http://docs.python.org/reference/datamodel.html#object. rmul
28 Torsten Marek [2008-09-20 17:31:00]
Перемещение 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.
28 Ber [2008-09-19 16:16:00]
Функции Getter в операторе модуля
Функции attrgetter()
и itemgetter()
в модуле operator
могут использоваться для создания функций быстрого доступа для использования в сортировочных и поисковых объектах и словарях
Глава 6.7 в Документах библиотеки Python
27 ianb [2008-09-22 08:33:00]
Распаковка пакетов:
>>> (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)
27 tadeusz [2008-09-29 13:36:00]
Очевидно, модуль антигравитации. xkcd # 353
26 davidavr [2008-09-19 23:30:00]
Интерпретатор Python
>>>
Возможно, не менее известный, но, безусловно, один из моих любимых функций Python.
25 Chmouel Boudjnah [2011-01-23 21:24:00]
Простота:
>>> 'str' in 'string'
True
>>> 'no' in 'yes'
False
>>>
- это то, что я люблю в Python, я видел много не очень питонической идиомы, как это:
if 'yes'.find("no") == -1:
pass
25 Noctis Skytower [2009-12-01 05:09:00]
Синтаксис распаковки был обновлен в последней версии, как показано в примере.
>>> 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)
25 amix [2008-09-22 21:03:00]
Функция сортировки Python правильно сортирует кортежи (т.е. используя знакомый лексикографический порядок):
a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]
print sorted(a)
#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]
Полезно, если вы хотите отсортировать список лиц после возраста и затем назвать.
25 Jake [2008-10-21 16:26:00]
Ссылка на понимание списка по мере его создания...
Вы можете ссылаться на понимание списка, поскольку оно создается символом "_ [1]". Например, следующая функция уникальна: исключает список элементов без изменения их порядка, ссылаясь на его понимание списка.
def unique(my_list):
return [x for x in my_list if x not in locals()['_[1]']]
11 Martin Beckett [2008-10-15 21:37:00]
Небольшая ошибка в python. Обычным быстрым способом объединения списка строк является
''.join(list_of_strings)
11 dan_waterworth [2011-03-05 11:26:00]
11 Chinmay Kanchi [2010-01-14 01:58:00]
Создание перечислений
В 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
11 asmeurer [2010-12-28 09:18:00]
Модель данных объекта
Вы можете переопределить любой оператор на языке для своих собственных классов. См. эту страницу для получения полного списка. Некоторые примеры:
-
Вы можете переопределить любой оператор (
* + - / // % ^ == < > <= >= .
и т.д.). Все это делается путем переопределения__mul__
,__add__
и т.д. В ваших объектах. Вы можете даже переопределить такие вещи, как__rmul__
для обработки отдельноyour_object*something_else
иsomething_else*your_object
..
- это доступ к атрибутам (a.b
) и может быть переопределен для обработки любых произвольныхb
с помощью__getattr__
. Также здесь используетсяa(…)
с помощью__call__
. -
Вы можете создать свой собственный синтаксис slice (
a[stuff]
), который может быть очень сложным и сильно отличается от стандартного синтаксиса, используемого в списках (numpy имеет хороший пример мощности этого в своих массивах), используя любую комбинацию,
,:
и…
, которая вам нравится, используя объекты Slice. -
Обращайтесь с тем, что происходит со многими ключевыми словами на языке. Включены
del
,in
,import
иnot
. -
Обратите внимание на то, что происходит, когда многие встроенные функции вызываются вместе с вашим объектом. Стандартные
__int__
,__str__
и т.д. Идут здесь, но так же__len__
,__reversed__
,__abs__
и три аргумента__pow__
(для модульного возведения в степень).
10 csl [2008-09-23 13:34:00]
"Распаковка" для функциональных параметров
def foo(a, b, c):
print a, b, c
bar = (3, 14, 15)
foo(*bar)
При выполнении отпечатков:
3 14 15
10 sprintf [2009-01-02 22:10:00]
Дзен Питона
>>> 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 a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let do more of those!
10 Christian Oudard [2009-01-02 21:48:00]
Встроенный reversed()
. Во многих случаях он делает гораздо более чистым.
быстрый пример:
for i in reversed([1, 2, 3]):
print(i)
дает:
3
2
1
Однако reversed()
также работает с произвольными итераторами, такими как строки в файле или выражения генератора.
10 Foo Bah [2011-02-10 18:14:00]
Изменение метки функции во время выполнения:
>>> 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
...
10 Roman Bodnarchuk [2011-07-04 21:11:00]
string-escape
и unicode-escape
encodings
Допустим, у вас есть строка из внешнего источника, содержащая \n
, \t
и т.д. Как преобразовать их в новую строку или вкладку? Просто декодируйте строку, используя string-escape
кодировку!
>>> print s
Hello\nStack\toverflow
>>> print s.decode('string-escape')
Hello
Stack overflow
Другая проблема. У вас нормальная строка с литералами в формате unicode, например \u01245
. Как заставить его работать? Просто декодируйте строку, используя unicode-escape
encoding!
>>> 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')
Привіт, світ!
9 Johnsyweb [2011-07-09 05:09:00]
Сжатие 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]
9 cerberos [2011-07-18 18:39:00]
Образец Борга
Это убийца из Alex Martelli. Все экземпляры состояния Borg
общего доступа. Это устраняет необходимость использования шаблона singleton (экземпляры не имеют значения при совместном использовании состояния) и довольно элегантны (но сложнее с новыми классами).
Значение foo
может быть переназначено в любом случае, и все будет обновлено, вы даже можете переназначить весь dict. Borg - идеальное имя, читайте здесь.
class Borg:
__shared_state = {'foo': 'bar'}
def __init__(self):
self.__dict__ = self.__shared_state
# rest of your class here
Это идеально подходит для совместного использования eventlet.GreenPool для управления concurrency.
9 L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ [2010-05-24 19:38:00]
Топ-секретные атрибуты
>>> 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'
9 Lakshman Prasad [2009-03-02 21:16:00]
Создание словаря двух последовательностей, имеющих связанные данные
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}
9 Apalala [2011-01-08 01:00: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
.
9 FernandoEscher [2011-01-24 09:13:00]
Динамически добавленные атрибуты
Это может быть полезно, если вы подумали о добавлении некоторых атрибутов в свои классы, просто вызвав их. Это можно сделать, переопределив __getattribute__
функция-член, которая вызывается, когда используется точечный операнд. Итак, давайте посмотрим на фиктивный класс:
class Dummy(object):
def __getattribute__(self, name):
f = lambda: 'Hello with %s'%name
return f
Когда вы создаете экземпляр объекта Dummy и выполняете вызов метода, вы получаете следующее:
>>> d = Dummy()
>>> d.b()
'Hello with b'
Наконец, вы можете даже установить атрибут для своего класса, чтобы он мог быть динамически определен. Это может быть полезно, если вы работаете с веб-фреймами Python и хотите делать запросы, анализируя имя атрибута.
У меня есть gist в github с помощью этого простого кода и его эквивалента на Ruby сделанный другом.
Будьте осторожны!
9 Paddy3118 [2008-09-22 09:32:00]
разархивировать ненужное в Python
Кто-то написал о том, что Python не имеет функции распаковки для работы с zip(). unzip - это прямое вычисление, потому что:
>>> t1 = (0,1,2,3)
>>> t2 = (7,6,5,4)
>>> [t1,t2] == zip(*zip(t1,t2))
True
При отражении, однако, я бы предпочел бы явный unzip().
8 haridsv [2010-04-06 03:58:00]
threading.enumerate() предоставляет доступ ко всем объектам Thread в системе, а sys._current_frames() возвращает текущие фреймы стека всех потоков в системе, поэтому объедините эти два и вы получите дампы стеков Java style:
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. Вы также можете выбрать сигнал .SIGUSR1 или signal.SIGUSR2.
8 Tom Viner [2009-01-12 14:38:00]
pdb - Отладчик Python
Как программист, одной из первых вещей, которые необходимы для серьезной разработки программы, является отладчик. У Python есть один встроенный модуль, который доступен как модуль под названием pdb (для "Python DeBugger", естественно!).
7 Ken Arnold [2009-06-09 06:27:00]
Перезагрузка модулей позволяет использовать стиль "живого кодирования". Но экземпляры классов не обновляются. Вот почему, и как обойти это. Помните, все, да, все это объект.
>>> 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 the old class object
>>> obj.__class__ = a_module.SomeClass # pick up the new class
>>> obj.method()
(new method output)
Это "работает с ножницами", потому что внутреннее состояние объекта может отличаться от того, что ожидает новый класс. Это работает для действительно простых случаев, но помимо этого, pickle
- ваш друг. По-прежнему полезно понять, почему это работает.
7 Steen [2008-11-28 23:34:00]
... что dict.get()
имеет значение по умолчанию, тем самым избегая KeyErrors:
In [1]: test = { 1 : 'a' }
In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'> Traceback (most recent call last)
<ipython console> 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
7 Denilson Sá Maia [2010-08-21 00:38:00]
Обратные косые черты внутри сырых строк все еще могут скрываться от кавычек. Смотрите это:
>>> print repr(r"aaa\"bbb")
'aaa\\"bbb'
Обратите внимание, что как обратная косая черта, так и двойная кавычка присутствуют в последней строке.
Как следствие, вы не можете закончить необработанную строку с обратной косой чертой:
>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\\"'
Это происходит из-за того, что были реализованы необработанные строки, которые помогают писать регулярные выражения, а не писать пути Windows. Прочитайте длинную дискуссию об этом на Gotcha - обратная косая черта в именах файлов Windows.
7 Elisha [2011-06-26 23:04:00]
бесконечная рекурсия в списке
>>> 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
7 Pratik Deoghare [2009-03-11 01:47:00]
inspect модуль также является отличной функцией.
7 Brendon Crawford [2011-01-23 20:37:00]
Операторы можно назвать функциями:
from operator import add
print reduce(add, [1,2,3,4,5,6])
6 grayger [2009-12-03 07:23:00]
Манипулирование пределом рекурсии
Получение или установка максимальной глубины рекурсии с помощью sys.getrecursionlimit() и sys.setrecursionlimit().
Мы можем ограничить его, чтобы предотвратить переполнение стека, вызванное бесконечной рекурсией.
6 Paweł Hajdan [2008-09-19 16:19:00]
Возможность подменить даже такие вещи, как удаление файлов, открытие файлов и т.д. - прямая манипуляция языковой библиотекой. Это огромное преимущество при тестировании . Вам не нужно обертывать все в сложных контейнерах. Просто замените функцию/метод и идите. Это также называется патчем обезьяны.
6 Markus [2009-06-18 18:45:00]
Вы можете украсить функции классами - заменив функцию экземпляром класса:
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)
6 Armin Ronacher [2008-09-22 01:12:00]
Встроенные методы или функции не реализуют протокол дескриптора, который делает невозможным делать такие вещи следующим образом:
>>> 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
6 Mykola Kharechko [2009-02-25 13:29:00]
Объекты небольших intgers (-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
>>>
6 Benjamin Peterson [2009-01-01 19:14:00]
Вы можете переопределить 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'>)
Вероятно, он скрыт по уважительной причине.:)
0 Giampaolo Rodolà [2011-12-07 21:49:00]
В Python 2 вы можете сгенерировать строковое представление выражения, заключая его в обратные ссылки:
>>> `sorted`
'<built-in function sorted>'
Это исчезло в python 3.X.
0 Srinivas Reddy Thatiparthy [2012-01-09 11:57:00]
некоторые интересные функции с сокращением и оператором.
>>> 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
0 inspectorG4dget [2011-05-26 21:01:00]
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
0 shadowland [2011-10-21 19:43:00]
Интерактивная отладка сценариев (и строк доктрины)
Я не думаю, что это так широко известно, как могло бы быть, но добавьте эту строку в любой python script:
import pdb; pdb.set_trace()
приведет к тому, что отладчик PDB появится с курсором пробега в этой точке кода. Что еще менее известно, я думаю, это то, что вы можете использовать ту же строку в доктрине:
"""
>>> 1 in (1,2,3)
Becomes
>>> import pdb; pdb.set_trace(); 1 in (1,2,3)
"""
Затем вы можете использовать отладчик для проверки среды doctest. Вы действительно не можете пройти через доктрину, потому что каждая строка работает автономно, но это отличный инструмент для отладки globs и окружающей среды doctest.
0 Rabarberski [2011-05-25 13:47:00]
Умножьте строку, чтобы ее повторить
print "SO"*5
дает
SOSOSOSOSO
0 giodamelio [2011-09-05 10:46:00]
Вот полезная функция, которую я использую при отладке ошибок типа
def typePrint(object):
print(str(object) + " - (" + str(type(object)) + ")")
Он просто печатает вход, за которым следует тип, например
>>> a = 101
>>> typePrint(a)
101 - (<type 'int'>)
0 Martin Thurau [2009-12-24 16:30:00]
Вы можете построить функции kwargs по запросу:
kwargs = {}
kwargs[str("%s__icontains" % field)] = some_value
some_function(**kwargs)
Вызов str() каким-то образом необходим, поскольку python жалуется, что это не строка. Не знаю, почему;) Я использую это для динамических фильтров в объектной модели Djangos:
result = model_class.objects.filter(**kwargs)
-2 M. Utku ALTINKAYA [2008-11-27 06:24:00]
is_ok() and "Yes" or "No"
-2 bfontaine [2011-09-26 22:55:00]
for line in open('foo'):
print(line)
который эквивалентен (но лучше):
f = open('foo', 'r')
for line in f.readlines():
print(line)
f.close()
-5 Abdelouahab [2011-07-28 01:52:00]
чтобы активировать автозаполнение в среде IDE, которая принимает его (например, IDLE, Editra, IEP) вместо того, чтобы делать: "Здравствуй". (а затем вы нажмете TAB), вы можете обмануть в среде IDE, просто сделайте hi ". (и вы нагреваете TAB) (как видите, в начале нет отдельной цитаты), потому что она будет следовать только за последней пунктуацией, она нравится, когда вы добавляете: и нажмите enter, она добавляет непосредственно отступы, dont знайте, если он внесет изменения, но это не будет больше:)
-9 L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ [2010-05-13 23:23:00]
Скобы
def g():
print 'hi!'
def f(): (
g()
)
>>> f()
hi!
24 Tom [2009-06-02 12:12:00]
Мне лично нравится 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
24 Matthias Kestenholz [2008-09-19 14:55:00]
Метаклассы
конечно:-) Что такое метакласс в Python?
23 Robert Rossney [2008-10-03 03:01:00]
Генераторы
Я думаю, что многие начинающие разработчики Python передают генераторы, не понимая, для чего они хотят, или чувствуют свою силу. Только после того, как я прочитал презентацию Дэвида М. Бэйзли Пикона о генераторах (это доступно здесь), я понял, насколько полезен (необходим, действительно) они есть. В этой презентации освещалось то, что было для меня совершенно новым способом программирования, и я рекомендую его всем, у кого нет глубокого понимания генераторов.
22 e-satis [2008-09-19 16:39:00]
Неявная конкатенация:
>>> print "Hello " "World"
Hello World
Полезно, если вы хотите сделать длинный текст подходящим для нескольких строк в script:
hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \
"Word"
или
hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello "
"Word")
22 Giampaolo Rodolà [2010-07-15 12:03:00]
При использовании интерактивной оболочки "_" содержит значение последнего напечатанного элемента:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> _
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
22 David Z [2010-07-24 23:25:00]
Нулевой аргумент и переменный аргумент lambdas
Лямбда-функции обычно используются для быстрого преобразования одного значения в другое, но их также можно использовать для обертывания значения в функции:
>>> f = lambda: 'foo'
>>> f()
'foo'
Они также могут принимать обычный синтаксис *args
и **kwargs
:
>>> g = lambda *args, **kwargs: args[0], kwargs['thing']
>>> g(1, 2, 3, thing='stuff')
(1, 'stuff')
22 Remco Wendt [2010-07-22 17:47:00]
Функция утилиты textwrap.dedent
в python может пригодиться при проверке того, что возвращаемая многострочная строка равна ожидаемому результату без нарушения отступы ваших unittests:
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)
Использование аргументов ключевого слова как назначения
Иногда хочется построить ряд функций в зависимости от одного или нескольких параметров. Однако это может легко привести к закрытию всех ссылок на один и тот же объект и значение:
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
20 jpsimons [2009-12-06 01:10:00]
Мод работает правильно с отрицательными номерами
-1% 5 4, как и должно быть, а не -1, как на других языках, таких как JavaScript. Это делает очиститель "wraparound windows" на Python, вы просто это делаете:
index = (index + increment) % WINDOW_SIZE
19 Torsten Marek [2008-09-25 21:22:00]
Назначение и удаление фрагментов:
>>> 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]
) назначенный итерабель должен иметь такую же длину, что и срез.
19 Evgeny [2010-05-26 23:25:00]
Хорошая обработка бесконечной рекурсии в словарях:
>>> a = {}
>>> b = {}
>>> a['b'] = b
>>> b['a'] = a
>>> print a
{'b': {'a': {...}}}
19 Markus [2009-06-18 18:40:00]
Не очень скрытые, но функции имеют атрибуты:
def doNothing():
pass
doNothing.monkeys = 4
print doNothing.monkeys
4
19 Jeremy Cantrell [2008-09-20 05:55:00]
Первоклассные функции
Это не действительно скрытая функция, но тот факт, что функции являются объектами первого класса, просто велик. Вы можете передать их, как и любую другую переменную.
>>> 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".'
19 evilpie [2010-03-20 11:58:00]
Передача кортежа в встроенные функции
Многие функции Python принимают кортежи, также это не похоже. Например, вы хотите проверить, является ли ваша переменная числом, вы можете:
if isinstance (number, float) or isinstance (number, int):
print "yaay"
Но если вы передадите нам кортеж, это выглядит намного чище:
if isinstance (number, (float, int)):
print "yaay"
19 Alexander Kojevnikov [2008-09-23 02:22:00]
Тернарный оператор
>>> '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'
18 Marcin Swiderski [2010-07-14 11:14:00]
изменение итерации с помощью отрицательного шага
>>> 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]
18 Kimvais [2011-03-09 22:37:00]
Возможно, это не функция программирования как таковая, но настолько полезная, что я все равно отправлю ее.
$ python -m http.server
... затем $ wget http://<ipnumber>:8000/filename
где-то еще.
Если вы все еще используете старшую (2.x) версию Python:
$ python -m SimpleHTTPServer
Вы также можете указать порт, например. python -m http.server 80
(поэтому вы можете опустить порт в URL-адресе, если у вас есть корень на стороне сервера)
18 Noufal Ibrahim [2010-12-21 19:24:00]
Не "скрыто", но довольно полезно и не используется обычно
Создание функции объединения строк так быстро
comma_join = ",".join
semi_join = ";".join
print comma_join(["foo","bar","baz"])
'foo,bar,baz
и
Возможность создания списков строк более элегантно, чем цитата, запятая.
l = ["item1", "item2", "item3"]
заменен на
l = "item1 item2 item3".split()
17 Piotr Duda [2010-07-18 23:59:00]
Из словаря python 3.1 (2.7) и набора понятий поддерживаются:
{ a:a for a in range(10) }
{ a for a in range(10) }
17 David Z [2010-06-29 21:25:00]
Несколько ссылок на итератор
Вы можете создать несколько ссылок на один и тот же итератор, используя умножение списка:
>>> 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
documentation
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
15 u0b34a0f6ae [2009-11-06 16:18:00]
Python может понимать любые цифры юникода, а не только тип ASCII:
>>> s = u'10585'
>>> s
u'\uff11\uff10\uff15\uff18\uff15'
>>> print s
10585
>>> int(s)
10585
>>> float(s)
10585.0
14 Armin Ronacher [2008-09-22 01:02:00]
__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}
14 Thomas Wouters [2010-02-14 00:12:00]
Манипулирование 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
выполнять обычный поиск модуля, даже если он уже был импортирован раньше.
14 John D. Cook [2010-07-14 05:06:00]
Вы можете задать любой объект, из которого он пришел, просмотрев его свойство __ module__. Это полезно, например, если вы экспериментируете в командной строке и импортируете много вещей.
В одних и тех же строках вы можете запросить модуль, откуда он пришел, просмотрев его свойство __ file__. Это полезно при отладке путей.
14 Xavier Martinez-Hidalgo [2009-12-31 02:35:00]
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.
13 daniel [2008-09-20 23:09:00]
Некоторые из встроенных избранных, map(), reduce() и filter(). Все очень быстрые и мощные.
13 Ken Arnold [2009-06-09 06:14:00]
Одно слово: IPython
Интроспекция вкладок, красивая печать, %debug
, управление историей, pylab
,... хорошо стоит время, чтобы хорошо учиться.
13 Xavier Martinez-Hidalgo [2009-12-31 02:29:00]
Предполагаемая целочисленная база
>>> 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
12 Denis Otkidach [2009-10-27 18:49:00]
Расширение свойств (определяемых как дескриптор) в подклассах
Иногда полезно увеличить (изменить) значение "возвращено" дескриптором в подклассе. Это можно легко сделать с помощью 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
опция выполнила script и позволяет продолжить в интерактивном режиме):
>>> B().prop
{'a': 1, 'b': 2}
12 Dan Lenski [2008-09-23 02:56:00]
Вы можете создать словарь из набора последовательностей длиной-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}
4 cleg [2008-09-19 14:55:00]
Специальные методы
4 e-satis [2011-12-24 18:49:00]
У Python есть исключения для очень неожиданных вещей:
Импорт
Это позволяет импортировать альтернативу, если отсутствует lib
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
В то время как это более подробно для одной проверки, можно сократить несколько проверок смешивания исключений и логических операторов с тем же сообщением об ошибке.
4 Markus [2009-06-18 18:54:00]
Благодаря небольшому объему работы модуль потоковой передачи становится удивительно простым в использовании. Этот декоратор меняет функцию так, чтобы она выполнялась в своем собственном потоке, возвращая экземпляр класса-заполнителя вместо его обычного результата. Вы можете проверить ответ, проверив 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
4 Tupteq [2008-10-20 14:59:00]
Замена метода для экземпляра объекта
Вы можете заменить методы уже созданных экземпляров объектов. Он позволяет создавать экземпляр объекта с различными (исключительными) функциональными возможностями:
>>> 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>
Node: Это решение не должно использоваться как общая замена механизма наследования! Но это может быть очень удобно в некоторых конкретных ситуациях (отладка, насмешка).
Предупреждение: Это решение не будет работать для встроенных типов и для новых классов стиля с использованием слотов.
3 Don O'Donnell [2010-07-19 18:51:00]
** Using sets to reference contents in sets of 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:
Обратите внимание, что аргумент
elem
для__contains__()
,remove()
иdiscard()
методы могут быть множеством. Чтобы поддержать поиск эквивалентного frozenset,elem
набор временно мутируется во время поиска и затем восстанавливается. В течение поиск, наборelem
не должен читаться или мутировать, поскольку он не имеют значимую ценность.
К сожалению, и, что удивительно, это не относится к словарям:
>>> 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'
3 Lakshman Prasad [2009-03-02 21:23:00]
Имитация третичного оператора с использованием и и/или
и/или операторы в python возвращают сами объекты, а не Booleans. Таким образом:
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
Ну, это работает, если вы уверены, что ваше истинное предложение не оценивается 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
3 Thomas Wouters [2008-09-19 16:51:00]
Все динамическое
"Время компиляции не существует". Все в Python - это время исполнения. Модуль "определяется", выполняя исходный код модуля сверху вниз, как и script, а результирующее пространство имен - это пространство атрибутов модуля. Аналогично, класс "определяется", выполняя тело класса сверху вниз, а результирующее пространство имен - это пространство атрибутов класса. Тело класса может содержать полностью произвольный код, включая операторы импорта, циклы и другие инструкции класса. Создание класса, функции или даже модуля "динамически", как его иногда просят, не сложно; на самом деле этого невозможно избежать, поскольку все "динамично".
3 Steven Sproat [2009-07-06 20:28:00]
Если вы переименовали класс в своем приложении, где вы загружаете файлы, сохраненные пользователем, через Pickle, а один из переименованных классов хранится в старом сохраненном пользователем, вы не сможете загрузить этот маринованный файл.
Однако просто добавьте ссылку на определение класса и все хорошее:
например, до:
class Bleh:
pass
теперь
class Blah:
pass
Таким образом, ваш пользовательский маринованный сохраненный файл содержит ссылку на Bleh, которая не существует из-за переименования. Исправить?
Bleh = Blah
просто!
3 Greg [2009-08-27 05:14:00]
Тот факт, что ВСЕ - это объект, и как таковой расширяем. Я могу добавить переменные-члены как метаданные к функции, которую я определяю:
>>> def addInts(x,y):
... return x + y
>>> addInts.params = ['integer','integer']
>>> addInts.returnType = 'integer'
Это может быть очень полезно для написания динамических модульных тестов, например.
Функциональная поддержка.
Генераторы и выражения генератора, в частности.
Ruby снова сделал этот мейнстрим, но Python тоже может это сделать. Не так повсеместно в библиотеках, как в Ruby, что слишком плохо, но мне нравится синтаксис лучше, проще.
Потому что они не такие вездесущие, я не вижу в них столько примеров, почему они полезны, но они позволили мне написать более чистый и эффективный код.
3 zaphod [2008-10-17 05:19:00]
Частные методы и скрытие данных (инкапсуляция)
В 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.
3 Ivan P [2011-02-23 00:34:00]
Python имеет "private" переменные
Переменные, которые начинаются, но не заканчиваются, с двойным подчеркиванием становятся частными, а не только по соглашению. На самом деле __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']
>>>
3 Constantin [2008-09-23 20:48:00]
Объекты в булевом контексте
Пустые кортежи, списки, dicts, строки и многие другие объекты эквивалентны 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
3 matchew [2011-06-30 04:04:00]
пока вы не очень pythonic, вы можете записать в файл с помощью print
print>>outFile, 'I am Being Written'
Эта форма иногда называется "
write()
, как описано выше. В этой расширенной форме последующие выражения печатаются на этот файл-объект. Если первая выражение оценивается какNone
, тогдаsys.stdout
используется как файл для выход.
3 six8 [2009-10-20 09:35:00]
Простой способ проверить, находится ли ключ в dict:
>>> 'key' in { 'key' : 1 }
True
>>> d = dict(key=1, key2=2)
>>> if 'key' in d:
... print 'Yup'
...
Yup
3 etuardu [2011-10-12 18:27:00]
Печать многострочных строк по одному экрану за раз
Не очень полезная функция, скрытая в классе 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:
2 jfs [2009-03-17 03:56:00]
Модуль 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>
Классы как объекты первого класса (показаны с помощью определения динамического класса)
Обратите внимание на использование крышки. Если этот конкретный пример выглядит как "правильный" подход к проблеме, тщательно передумайте... несколько раз:)
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
2 Luper Rouch [2011-03-09 22:24:00]
Совсем не скрытая функция, но все же хорошая:
import os.path as op
root_dir = op.abspath(op.join(op.dirname(__file__), ".."))
Сохраняет много символов при манипулировании путями!
2 Mojo_Jojo [2011-05-27 17:08:00]
Используется xrange (INT) вместо диапазона (INT).... У него меньше использования памяти и на самом деле не зависит от размера целого. Yey!! Разве это не хорошо?
Управление памятью
Python динамически выделяет память и использует сборку мусора для восстановления неиспользуемого пространства. Когда объект выходит за пределы области действия, и никакие другие переменные не ссылаются на него, он будет восстановлен. Мне не нужно беспокоиться о переполнении буфера и медленно растущих серверных процессах. Управление памятью также является особенностью других динамических языков, но Python просто делает это так хорошо.
Конечно, мы должны следить за циркулярными ссылками и поддерживать ссылки на объекты, которые больше не нужны, но слабые ссылки здесь помогают.
2 Armin Ronacher [2008-09-22 00:49:00]
Если вы используете 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
2 primpap [2012-01-21 09:22:00]
Не действительно скрытая функция, но что-то, что может пригодиться.
для прокрутки элементов в списке попарно
for x, y in zip(s, s[1:]):
2 eryksun [2009-11-14 16:05:00]
Что касается реализации Ником Джонсоном класса свойств (просто демонстрация дескрипторов, конечно, не замена встроенного), я бы включил setter, который вызывает 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'
Включение setter делает это дескриптором данных в отличие от дескриптора метода/не-данных. Дескриптор данных имеет приоритет над экземплярами словарей экземпляра. Теперь экземпляр не может иметь другой объект, назначенный для имени свойства, и попытки присвоить его свойство вызовут ошибку атрибута.
2 Giampaolo Rodolà [2012-02-02 20:16:00]
>>> float('infinity')
inf
>>> float('NaN')
nan
Дополнительная информация:
2 Busted Keaton [2009-09-09 16:01:00]
Встроенная функция 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 (здесь)
1 sransara [2011-12-09 10:18:00]
Не функция программирования, но полезна при использовании Python с bash
или shell scripts
.
python -c"import os; print(os.getcwd());"
Смотрите документацию python здесь. Дополнительные примечания, которые следует учитывать при написании более длинных сценариев Python, можно увидеть в этой дискуссии.
1 locojay [2011-06-19 18:35:00]
mapreduce с использованием карты и сокращения функций
создать простой sumproduct таким образом:
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
1 Kevin Little [2008-09-19 16:25:00]
>>> 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]']" - это "секретное имя" создаваемого списка. Очень полезно, когда состояние создаваемого списка влияет на последующие решения сборки.
1 Perkins [2012-01-14 00:35:00]
Позиции 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]))
6 yoav.aviram [2011-12-29 19:55:00]
Цепочки округления: 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
Спасибо Грегор.
6 hughdbrown [2010-07-22 23:03:00]
Срезки как lvalues. Это сито из Eratosthenes создает список, который имеет либо простое число, либо 0. Элементы равны 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)
Для работы срез слева должен быть назначен список справа от той же длины.
6 Daniel Hepper [2010-07-16 16:46:00]
Ломтики и мутность
Копирование списков
>>> 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]
6 Martin [2010-07-19 15:01:00]
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,)
6 ironfroggy [2008-10-13 02:19:00]
Вложенная функция Параметр Повторная привязка
def create_printers(n):
for i in xrange(n):
def printer(i=i): # Doesn't work without the i=i
print i
yield printer
5 Douglas [2011-06-20 17:54:00]
Простой встроенный инструмент сравнения производительности
Стандартная библиотека 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
5 pi. [2008-09-19 18:55:00]
Слишком ленив, чтобы инициализировать каждое поле в словаре? Нет проблем:
В 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)
UPDATE:
Спасибо Кен Арнольд. Я пересмотрел более сложную версию 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)
5 Justin [2012-01-18 19:17:00]
Установить понимание
>>> {i**2 for i in range(5)}
set([0, 1, 4, 16, 9])
5 Justin [2012-01-18 19:12:00]
Познания Диктата
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
5 Armin Ronacher [2008-09-22 00:57:00]
Если вы используете дескрипторы на своих классах, 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()
в чистоте.
5 tghw [2008-09-22 21:48:00]
__ GetAttr __()
getattr
- действительно хороший способ создания общих классов, что особенно полезно, если вы пишете API. Например, в API-интерфейсе FogBugz Python getattr
используется для беспрепятственного пропуска вызовов метода в веб-службу:
class FogBugz:
...
def __getattr__(self, name):
# Let 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. Любые ошибки будут отправляться веб-службой и передаваться пользователю.
Отображение Mutable Buffers
Использование протокола Python Buffer Protocol для отображения изменяемых байт-ориентированных буферов в Python (2.5/2.6).
(К сожалению, здесь нет кода. Требуется использование низкоуровневого API C или существующего адаптера).
5 Ken Arnold [2011-06-14 04:49:00]
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)
(btw, 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
но вам не нужно убеждать всех унаследовать от вашего базового класса, просто чтобы установить атрибут.
5 Abbafei [2011-02-17 04:44:00]
Я не уверен, где (или это) это в документах Python, но для python 2.x(как минимум 2.5 и 2.6, которые я только что пробовал), оператор print
можно вызвать с помощью parenthenses. Это может быть полезно, если вы хотите легко переносить некоторый код Python 2.x на Python 3.x.
Пример:
print('We want Moshiach Now')
должен печатать We want Moshiach Now
работать в python 2.5, 2.6 и 3.x.
Кроме того, оператор not
может быть вызван с parenthenses в Python 2 и 3:
not False
а также
not(False)
должны оба вернуть True
.
Parenthenses также может работать с другими операторами и операторами.
РЕДАКТИРОВАТЬ: НЕ рекомендуется помещать родительские концы вокруг операторов not
(и, возможно, любых других операторов), так как это может сделать для неожиданных ситуаций, например (это происходит потому, что родительские имена просто действительно вокруг 1
):
>>> (not 1) == 9
False
>>> not(1) == 9
True
Это также может работать для некоторых значений (я думаю, что это не допустимое имя идентификатора), например:
not'val'
должен возвращать False
, а print'We want Moshiach Now'
должен возвращать We want Moshiach Now
. (но not552
поднимет NameError, так как он является допустимым именем идентификатора).
5 armandino [2011-03-05 11:06:00]
В дополнение к этому ранее haridsv:
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
это также можно сделать:
>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)
5 MatToufoutu [2011-08-16 13:03:00]
Вот 2 пасхальных яйца:
Один в самом python:
>>> 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://localhost:8080/?macgybarchakku, вы увидите пасхальное яйцо.
5 Oko [2008-09-19 14:53:00]
Список понятий
Сравните более традиционные (без понимания списка):
foo = []
for x in xrange(10):
if x % 2 == 0:
foo.append(x)
в
foo = [x for x in xrange(10) if x % 2 == 0]
5 Gurch [2008-10-16 13:52:00]
5 Chinmay Kanchi [2010-01-14 01:46:00]
Объекты 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!')
5 Amol [2009-11-03 16:10:00]
Питоническая идиома 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.
4 pixelbeat [2008-10-13 01:40:00]
Использование динамической природы python для приложений config в синтаксисе python. Например, если у вас было следующее в файле конфигурации:
{
"name1": "value1",
"name2": "value2"
}
Тогда вы могли бы тривиально прочитать его, как:
config = eval(open("filename").read())
4 Apalala [2011-01-13 03:18:00]
Модуль экспортирует ВСЕ в своем пространстве имен
Включение имен, импортированных из других модулей!
# 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__ =
.
4 Ant [2011-01-07 19:00:00]
вставить vs append
не является признаком, но может быть интересным
Предположим, вы хотите вставить некоторые данные в список, а затем отменить его. самая легкая вещь
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 раз медленнее; это потому, что вставка - это O (n ^ 2), а append - O (n).
причина этой разницы заключается в том, что вставка должна перемещать каждый элемент в списке при каждом его вызове; append просто добавьте в конец списка эти элементы (иногда ему приходится перераспределять все, но все еще гораздо быстрее)
4 Dan Udey [2008-09-24 06:03:00]
Первоклассность всего ( "все - это объект" ), и это может привести к хаосу.
>>> 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 - философия "все является объектом", принятая до крайности, и методы, при помощи которых неправильное или плохо продуманное использование синтаксиса языка может привести к совершенно нечитаемому и незаметному коду спагетти, который вписывается в одно выражение.
4 Rafał Dowgird [2008-09-23 12:41:00]
Набор распаковки для циклов, списков и выражений генератора:
>>> 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
4 amix [2008-09-22 20:54:00]
Доступ к элементам словаря слова как атрибуты (свойства). поэтому, если a1 = AttrDict() имеет ключ 'name' → вместо a1 ['name'] мы можем легко атрибут имени доступа a1, используя → 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
4 Kabie [2011-03-27 05:29:00]
Идентификатор Unicode в Python3:
>>> 'Unicode字符_تكوين_Variable'.isidentifier()
True
>>> Unicode字符_تكوين_Variable='Python3 rules!'
>>> Unicode字符_تكوين_Variable
'Python3 rules!'
4 Wayne Werner [2010-07-16 21:42:00]
Объедините распаковку с функцией печати:
# 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)
4 Juanjo Conti [2010-02-14 01:09:00]
В Python нет секретов;)
4 haridsv [2010-04-06 03:47:00]
Вы можете назначить несколько переменных одному значению
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
Полезно для инициализации нескольких переменных в None, компактным способом.