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

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

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

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

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

119 ответов

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

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

Абсолютная мощность!

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

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

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

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

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

Тогда Вы могли тривиально считать его как:

config = eval(open("filename").read())
4
ответ дан 2 revs 23 May 2017 в 12:34
поделиться

При использовании дескрипторов на классах, 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
ответ дан Armin Ronacher 23 May 2017 в 12:34
поделиться

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

>>> 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
ответ дан Armin Ronacher 23 May 2017 в 12:34
поделиться

элементы Словаря Доступа как атрибуты (свойства). таким образом, если a1=AttrDict () имеет ключевое 'имя'-> вместо a1 ['имя'] мы можем легко получить доступ к атрибуту имени использования 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
ответ дан 2 revs, 2 users 80% 23 May 2017 в 12:34
поделиться

Объекты в булевом контексте

Пустые кортежи, списки, dicts, строки и много других объектов эквивалентны Лжи в булевом контексте (и непустой эквивалентны Истинному).

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

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

s = t or "Default value" # s will be assigned "Default value"
                         # if t is false/empty/none
3
ответ дан Constantin 23 May 2017 в 12:34
поделиться

Интерактивное заполнение клавишей Tab Интерпретатора

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.

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

__ getattr __ ()

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

class FogBugz:
    ...

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

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

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

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

параметр вложенной функции, снова переплетающий

def create_printers(n):
    for i in xrange(n):
        def printer(i=i): # Doesn't work without the i=i
            print i
        yield printer
6
ответ дан ironfroggy 23 May 2017 в 12:34
поделиться

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

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

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

91
ответ дан Rafał Dowgird 23 May 2017 в 12:34
поделиться
>>> x=[1,1,2,'a','a',3]
>>> y = [ _x for _x in x if not _x in locals()['_[1]'] ]
>>> y
[1, 2, 'a', 3]


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

1
ответ дан Kevin Little 23 May 2017 в 12:34
поделиться

При отладке сложных структур данных печать модуль прибывает удобный.

Заключение в кавычки из документов..

>>> 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']
36
ответ дан utku_karatas 23 May 2017 в 12:34
поделиться

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

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

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

Переповышение исключений :

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

оператор 'повышения' без аргументов в обработчике ошибок говорит Python повторно повышать исключение с оригиналом, traceback неповрежденный , позволяя Вам сказать, "о, извините, извините, я не означал ловить, это, извините, извините".

, Если Вы хотите распечатать, сохраните или играйте с исходным traceback, можно получить его с sys.exc_info (), и печать его как Python была бы делаться с 'traceback' модулем.

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

Python совершенствовался, операция разрезания имеет едва известный элемент синтаксиса, замещающий знак:

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

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

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

Можно использовать свойство для создания интерфейсов класса более строгими.

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

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

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

Встроенный 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'
46
ответ дан spiv 23 May 2017 в 12:34
поделиться

Отрицательный раунд

round() функция округляет число плавающее к данной точности в десятичных цифрах, но точность может быть отрицательной:

>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'

Примечание: round() всегда возвраты плавание, str() используемый в вышеупомянутом примере, потому что математические операции с плавающей точкой неточны, и под 2.x, второй пример может распечатать как 1234.5700000000001. Также посмотрите decimal модуль.

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

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

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

И затем если Вы хотите больше информации о конкретном методе, можно назвать "справку" на ней.

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

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

    Return a copy of the string S converted to uppercase.
48
ответ дан lacker 23 May 2017 в 12:34
поделиться

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

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

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

"Наиболее удобный способ [для изменения пути поиска Python] состоит в том, чтобы добавить конфигурационный файл пути к каталогу, это уже находится на пути Python, обычно к.../site-packages/каталог. Конфигурационные файлы пути имеют расширение .pth, и каждая строка должна содержать единственный путь, который будет добавлен к sys.path. (Поскольку новые пути добавляются к sys.path, модули в добавленных каталогах не переопределят стандартные модули. Это означает, что Вы не можете использовать этот механизм для установки исправленных версий стандартных модулей.)"

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

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

from __future__ import braces
314
ответ дан eduffy 23 May 2017 в 12:34
поделиться

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

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

Если Вы используете exec в функции, переменные правила поиска изменяются решительно. Закрытия больше не возможны, но Python позволяет произвольные идентификаторы в функции. Это дает Вам "модифицируемых местных жителей ()" и может привыкнуть к идентификаторам звездообразного импорта. На оборотной стороне это делает каждый поиск медленнее, потому что переменные заканчиваются в 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
ответ дан Armin Ronacher 23 May 2017 в 12:34
поделиться

Можно легко транспонировать массив с zip.

a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]
52
ответ дан 2 revs, 2 users 75% 23 May 2017 в 12:34
поделиться

проход () может взять вызываемый аргумент

, Например:

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

Эти iter(callable, until_value) функция неоднократно называет callable и приводит к своему результату, пока until_value не возвращается.

353
ответ дан 5 revs, 5 users 78% 23 May 2017 в 12:34
поделиться

set/frozenset

, Вероятно, легко пропущенный встроенный Python является "set/frozenset".

Полезный, когда Вы имеете список как это, [1,2,1,1,2,3,4] и только хотите uniques как это [1,2,3,4].

Используя набор () это точно, что Вы получаете:

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

И конечно получить количество uniques в списке:

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

можно также найти, является ли список подмножеством другого набора использования списка () .issubset ():

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

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

myset = {1,2,3,4}

, а также понимания набора:

{x for x in stuff}

для получения дополнительной информации: http://docs.python.org/library/stdtypes.html#set

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

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

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]
305
ответ дан Rafał Dowgird 23 May 2017 в 12:34
поделиться