Поскольку язык программирования Go не поддерживает в настоящее время общие типы, это будет трудно сделать.
В какой-то момент вполне могут быть добавлены дженерики. Мы не чувствуем для них неотложности, хотя мы понимаем, что некоторые программисты это делают.
Дженерики удобны, но они сложны по сложности в системе типов и времени выполнения. Мы еще не нашли дизайн, который дает ценность, пропорциональную сложности, хотя мы продолжаем думать об этом. Между тем, встроенные карты и фрагменты Go, а также возможность использования пустого интерфейса для создания контейнеров (с явным распаковкой) означают, что во многих случаях можно написать код, который будет делать какие дженерики будут разрешены, если будет менее плавным.
Это остается открытой проблемой.
blockquote>Посмотрите на пакет сортировки Go , чтобы увидеть, как он обрабатывает сравнения и другие операции, относящиеся к типу, путем определения sort.Interface с методами Len, Less и Swap.
Быть осторожными с изменяемыми параметрами по умолчанию
>>> 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]
объекты генераторов Создания
, Если Вы пишете
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)
От 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.
Для... еще синтаксиса ("еще" см. 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")
Слишком ленивый для инициализации каждого поля в словаре?Нет проблем:
В 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)
Основные сообщения:)
import this
# btw look at this module's source :)
<час> Дзэн Python, Tim Peters
Красивый лучше, чем ужасный.
Явный лучше, чем неявный.
Простой лучше, чем комплекс.
Комплекс лучше, чем сложный.
Плоский лучше, чем вложенный.
Редкий лучше, чем плотный.
количества Удобочитаемости.
Особые случаи не являются достаточно особенными для нарушения правил.
, Хотя практичность бьет чистоту.
Ошибки никогда не должны передавать тихо.
, Если явно не заставлено замолчать.
Перед лицом неоднозначности, откажитесь от искушения предположить. Должны быть один - и предпочтительно только один - очевидный способ сделать это.
, Хотя тот путь не может быть очевидным сначала, если Вы не голландцы.
Теперь лучше, чем никогда.
, Хотя никогда не часто лучше, чем [1 120] право теперь.
, Если реализацию трудно объяснить, это - плохая идея.
, Если реализацию легко объяснить, это может быть хорошая идея.
Пространства имен являются одной гудящей прекрасной идеей - давайте сделаем больше из тех!
... то, что 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
>>> 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 располагаться, но назвать его вторым разом с аргументом шага)
См. документация .
Исключение еще пункт:
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, повышенный кодом, защищаемым попыткой... кроме оператора.
Условное Присвоение
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 являются двумя классами.
Небольшая ошибка Python. Нормальный быстрый способ присоединиться к списку строк вместе,
''.join(list_of_strings)
>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"
, который является точно тем же как
>>> class NewType(object):
>>> x = "hello"
>>> n = NewType()
>>> n.x
"hello"
, Вероятно, не самая полезная вещь, но хороший знать.
Редактирование : Фиксированное название нового типа, должен быть NewType
, чтобы быть той же самой вещью как с class
оператор.
Редактирование : Скорректированный заголовок, чтобы более точно описать функцию.
Аргумент функции, распаковывающий
, можно распаковать список или словарь как аргументы функции с помощью *
и **
.
, Например:
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 широко используются в качестве контейнеров.
Оперативное значение, подкачивающее
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
, правая сторона присвоения является выражением, которое создает новый кортеж. Левая сторона присвоения сразу распаковывает тот (не имеющий ссылки) кортеж к именам a
и b
.
После присвоения, новый кортеж является не имеющим ссылки и отмечен для сборки "мусора", и значения, связанные с a
и b
, были подкачаны.
, Как отмечено в учебный раздел Python по структурам данных ,
Примечание, что несколько присвоение являются действительно просто комбинацией упаковки кортежа и распаковки последовательности.
конструктор dict принимает аргументы ключевого слова:
>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}
существует общая идиома в 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.
Часть из встроенный избранное, карта (), уменьшает (), и фильтр (). Все чрезвычайно быстрые и мощные.
Читаемые регулярные выражения
В 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})$"
, Словари имеют, 'получают ()' метод. Если Вы делаете d ['ключ'] и ключ не там, Вы получаете исключение. Если Вы делаете d.get ('ключ'), Вы не возвращаете Ни один, если 'ключ' не там. Можно добавить второй аргумент для возвращения того объекта вместо Ни одного, например: d.get ('ключ', 0).
Это является большим для вещей как сложение чисел:
sum[value] = sum.get(value, 0) + 1
>>> (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')
python -m SimpleHTTPServer 8000
>>> import atexit
% - форматирование берет словарь (также применяет %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))
замена Метода для экземпляра объекта
можно заменить методы уже экземпляров созданного объекта. Это позволяет Вам создавать экземпляр объекта с различной (исключительной) функциональностью:
>>> 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>
Узел: Это решение не должно использоваться в качестве общей замены механизма наследования! Но это может быть очень удобно в некоторых определенных ситуациях (отладка, дразня).
Предупреждение: Это решение не будет работать на встроенные типы и на модернизированные слоты использования классов.
Функциональная поддержка.
Генераторы и выражения генератора, конкретно.
Ruby сделал эту господствующую тенденцию снова, но Python может сделать это точно также. Не столь повсеместный в библиотеках как в Ruby, который слишком плох, но мне нравится синтаксис лучше, это более просто.
, поскольку они не так повсеместны, я не вижу как много примеров там на том, почему они полезны, но они позволили мне писать инструменту для очистки, более эффективному коду.
Присвоение и удаление частей:
>>> 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]
), присвоенное повторяемое должно иметь ту же длину как часть.
Кортеж, распаковывающий:
>>> (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)
__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}
перечисляют
Обертка, которую перечисляет повторяемое с, и она приведет к объекту наряду со своим индексом.
, Например:
>>> 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
>>>
Ссылки:
интерпретатор Python
>>>
, Возможно, не менее известный, но конечно одна из моих любимых функций Python.
Кортежи видов функции вида Python правильно (т.е. использование знакомого лексикографического порядка):
a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]
print sorted(a)
#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]
Полезный, если Вы хотите отсортировать список людей после возраста и затем назвать.