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

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

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

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

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

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

blockquote>

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

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

127 ответов

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
поделиться