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

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

Почему у Go нет общих типов?

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

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

Это остается открытой проблемой.

blockquote>

Посмотрите на пакет сортировки Go , чтобы увидеть, как он обрабатывает сравнения и другие операции, относящиеся к типу, путем определения sort.Interface с методами Len, Less и Swap.

1420
задан 30 revs, 24 users 18% 23 May 2017 в 12:34
поделиться

145 ответов

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

>>> 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]
339
ответ дан 2 revs, 2 users 67% 23 May 2017 в 12:34
поделиться

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

, Если Вы пишете

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

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

for n in x:

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

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

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

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

>>> 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
ответ дан 4 revs, 3 users 64% 23 May 2017 в 12:34
поделиться

От 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]}

существует также подкласс dict в 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.

258
ответ дан Armin Ronacher 23 May 2017 в 12:34
поделиться

Для... еще синтаксиса ("еще" см. http://docs.python.org/ref/for.html )

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

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

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

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")
288
ответ дан 3 revs, 3 users 67% 23 May 2017 в 12:34
поделиться

Слишком ленивый для инициализации каждого поля в словаре?Нет проблем:

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

ОБНОВЛЕНИЕ:

Спасибо Ken Arnold . Я повторно реализовал более сложную версию 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
ответ дан 4 revs 23 May 2017 в 12:34
поделиться

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

import this
# btw look at this module's source :)
<час>

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

Дзэн Python, Tim Peters

Красивый лучше, чем ужасный.
Явный лучше, чем неявный.
Простой лучше, чем комплекс.
Комплекс лучше, чем сложный.
Плоский лучше, чем вложенный.
Редкий лучше, чем плотный.
количества Удобочитаемости.
Особые случаи не являются достаточно особенными для нарушения правил.
, Хотя практичность бьет чистоту.
Ошибки никогда не должны передавать тихо.
, Если явно не заставлено замолчать.
Перед лицом неоднозначности, откажитесь от искушения предположить. Должны быть один - и предпочтительно только один - очевидный способ сделать это.
, Хотя тот путь не может быть очевидным сначала, если Вы не голландцы.
Теперь лучше, чем никогда.
, Хотя никогда не часто лучше, чем [1 120] право теперь.
, Если реализацию трудно объяснить, это - плохая идея.
, Если реализацию легко объяснить, это может быть хорошая идея.
Пространства имен являются одной гудящей прекрасной идеей - давайте сделаем больше из тех!

106
ответ дан 2 revs, 2 users 83% 23 May 2017 в 12:34
поделиться

... то, что dict.get() имеет значение по умолчанию ни из Одного, таким образом, избегая KeyErrors:

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

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

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

<type 'exceptions.KeyError'>: 2

In [3]: test.get( 2 )

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

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

и даже определить это 'на сцене':

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

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

>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar
7
ответ дан 3 revs, 3 users 67% 23 May 2017 в 12:34
поделиться
>>> 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]

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

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

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

40
ответ дан 2 revs, 2 users 80%jamesturk 23 May 2017 в 12:34
поделиться

Исключение еще пункт:

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

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

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

122
ответ дан 2 revs, 2 users 90% 23 May 2017 в 12:34
поделиться

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

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

, Хотя в определенный момент, это немного заходит слишком далеко.

Примечание, которое... еще можно использовать если в любом выражении. Например:

(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 являются двумя классами.

142
ответ дан 2 revs, 2 users 57% 23 May 2017 в 12:34
поделиться

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

''.join(list_of_strings)
11
ответ дан Martin Beckett 23 May 2017 в 12:34
поделиться

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

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

, который является точно тем же как

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

, Вероятно, не самая полезная вещь, но хороший знать.

Редактирование : Фиксированное название нового типа, должен быть NewType, чтобы быть той же самой вещью как с class оператор.

Редактирование : Скорректированный заголовок, чтобы более точно описать функцию.

183
ответ дан 4 revs, 3 users 87% 23 May 2017 в 12:34
поделиться

Аргумент функции, распаковывающий

, можно распаковать список или словарь как аргументы функции с помощью * и **.

, Например:

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)

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

222
ответ дан 4 revs, 3 users 74% 23 May 2017 в 12:34
поделиться

Оперативное значение, подкачивающее

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

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

, правая сторона присвоения является выражением, которое создает новый кортеж. Левая сторона присвоения сразу распаковывает тот (не имеющий ссылки) кортеж к именам a и b.

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

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

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

247
ответ дан 4 revs, 3 users 59% 23 May 2017 в 12:34
поделиться
is_ok() and "Yes" or "No"
-2
ответ дан M. Utku ALTINKAYA 23 May 2017 в 12:34
поделиться

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

>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}
32
ответ дан Henry Precheur 23 May 2017 в 12:34
поделиться

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

существует общая идиома в 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
ответ дан zaphod 23 May 2017 в 12:34
поделиться

Часть из встроенный избранное, карта (), уменьшает (), и фильтр (). Все чрезвычайно быстрые и мощные.

13
ответ дан daniel 23 May 2017 в 12:34
поделиться

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

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

соответствия именования В качестве примера (от ПРАКТИЧЕСКОЕ РУКОВОДСТВО Регулярного выражения )

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

Вы можете также verbosely писать regex, не используя 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})$"
235
ответ дан 3 revs, 3 users 67% 23 May 2017 в 12:34
поделиться

Словари имеют получать () метод

, Словари имеют, 'получают ()' метод. Если Вы делаете d ['ключ'] и ключ не там, Вы получаете исключение. Если Вы делаете d.get ('ключ'), Вы не возвращаете Ни один, если 'ключ' не там. Можно добавить второй аргумент для возвращения того объекта вместо Ни одного, например: d.get ('ключ', 0).

Это является большим для вещей как сложение чисел:

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

168
ответ дан 3 revs, 2 users 67% 23 May 2017 в 12:34
поделиться
  • подчеркивание, это содержит новое выходное значение, отображенное интерпретатором (на интерактивной сессии):
>>> (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
59
ответ дан 2 revs, 2 users 79% 23 May 2017 в 12:34
поделиться

Названное форматирование

% - форматирование берет словарь (также применяет %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.

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

Новый стиль, Форматирующий

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
138
ответ дан 5 revs, 5 users 73% 23 May 2017 в 12:34
поделиться

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

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

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

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

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

4
ответ дан Tupteq 23 May 2017 в 12:34
поделиться

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

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

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

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

3
ответ дан Karl Anderson 23 May 2017 в 12:34
поделиться

Присвоение и удаление частей:

>>> 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
ответ дан 2 revs, 2 users 89% 23 May 2017 в 12:34
поделиться

Кортеж, распаковывающий:

>>> (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
ответ дан 2 revs, 2 users 97% 23 May 2017 в 12:34
поделиться

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

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

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

>>> 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 модуль. Этим можно злоупотребить для получения dict значений:

>>> p.__reduce_ex__(2)[2][1]
{'y': 5, 'x': 3}
14
ответ дан Armin Ronacher 23 May 2017 в 12:34
поделиться

перечисляют

Обертка, которую перечисляет повторяемое с, и она приведет к объекту наряду со своим индексом.

, Например:


>>> 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
ответ дан 4 revs, 3 users 65% 23 May 2017 в 12:34
поделиться

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

>>> 

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

26
ответ дан davidavr 23 May 2017 в 12:34
поделиться

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

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

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

25
ответ дан 2 revs, 2 users 92% 23 May 2017 в 12:34
поделиться