Вопрос: Скрытые особенности Python [закрыты]


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

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

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


1420


источник


Ответы:


Цепочные операторы сравнения:

>>> 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, но с меньшим количеством ввода и каждый термин оценивается только один раз.


741



Получите дерево разбора 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)

512



перечислять

Оберните итерируемый с перечислением, и он даст элемент вместе с его индексом.

Например:


>>> 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
>>>

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


460



Creating generators objects

If you write

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

you can get out the generator and assign it to x. Now it means you can do

for n in x:

The advantage of this is that you don't need intermediate storage, which you would need if you did

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

In some cases this can lead to significant speed up.

You can append many if statements to the end of the generator, basically replicating nested for loops:

>>> 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)

419



iter() can take a callable argument

For instance:

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

The iter(callable, until_value) function repeatedly calls callable and yields its result until until_value is returned.


353



Be careful with mutable default arguments

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

Instead, you should use a sentinel value denoting "not given" and replace with the mutable you'd like as default:

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

339



Sending values into generator functions. For example having this function:

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

You can:

>>> 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

317



If you don't like using whitespace to denote scopes, you can use the C-style {} by issuing:

from __future__ import braces

314



The step argument in slice operators. For example:

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

The special case x[::-1] is a useful idiom for 'x reversed'.

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

305