Поскольку язык программирования Go не поддерживает в настоящее время общие типы, это будет трудно сделать.
В какой-то момент вполне могут быть добавлены дженерики. Мы не чувствуем для них неотложности, хотя мы понимаем, что некоторые программисты это делают.
Дженерики удобны, но они сложны по сложности в системе типов и времени выполнения. Мы еще не нашли дизайн, который дает ценность, пропорциональную сложности, хотя мы продолжаем думать об этом. Между тем, встроенные карты и фрагменты Go, а также возможность использования пустого интерфейса для создания контейнеров (с явным распаковкой) означают, что во многих случаях можно написать код, который будет делать какие дженерики будут разрешены, если будет менее плавным.
Это остается открытой проблемой.
blockquote>Посмотрите на пакет сортировки Go , чтобы увидеть, как он обрабатывает сравнения и другие операции, относящиеся к типу, путем определения sort.Interface с методами Len, Less и Swap.
Первоклассные функции
Это не действительно скрытая функция, но то, что функции являются объектами первого класса, является просто большим. Можно раздать их как любая другая переменная.
>>> def jim(phrase):
... return 'Jim says, "%s".' % phrase
>>> def say_something(person, phrase):
... print person(phrase)
>>> say_something(jim, 'hey guys')
'Jim says, "hey guys".'
Пример извлек из документации Python:
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
If the result is small enough to fit in an int, return an int.
Else return a long.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
"""
import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n: # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
_test()
функции Метода get в операторе
модуля функции attrgetter()
и itemgetter()
в модуле operator
могут использоваться для генерации функций с быстрым доступом для использования в сортировке и поисковых объектах и словарях
Глава 6.7 в Документах Библиотеки Python
"Распаковка" к параметрам функции
def foo(a, b, c):
print a, b, c
bar = (3, 14, 15)
foo(*bar)
, Когда выполняемая печать:
3 14 15
Декораторы
Декораторы позволяют обертывать функцию или метод в другой функции, которая может добавить функциональность, изменить аргументы или результаты, и т.д. Вы пишете декораторам одну строку выше функционального определения, начиная "в" знаке.
Пример показывает print_args
декоратор, который печатает аргументы украшенной функции прежде, чем назвать его:
>>> def print_args(function):
>>> def wrapper(*args, **kwargs):
>>> print 'Arguments:', args, kwargs
>>> return function(*args, **kwargs)
>>> return wrapper
>>> @print_args
>>> def write(text):
>>> print text
>>> write('foo')
Arguments: ('foo',) {}
foo
Генераторы
я думаю, что много начала разработчиков Python передает по генераторам, действительно не схватывая то, что они для или получение любого смысла их питания. Только когда я считал представление PyCon David M. Beazley генераторов (это доступно здесь ), что я понял, насколько полезный (важный, действительно) они. То представление осветило то, что было для меня совершенно новым способом запрограммировать, и я рекомендую его любому, у кого нет глубокого понимания генераторов.
Неявная конкатенация:
>>> print "Hello " "World"
Hello World
Полезный, когда Вы хотите сделать соответствие длинного текста на нескольких строках в сценарии:
hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \
"Word"
или
hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello "
"Word")
Используя аргументы ключевого слова как присвоения
Иногда каждый хочет создать диапазон из функций в зависимости от одного или нескольких параметров. Однако это могло бы легко привести к закрытиям все обращение к тому же объекту и значению:
funcs = []
for k in range(10):
funcs.append( lambda: k)
>>> funcs[0]()
9
>>> funcs[7]()
9
Этого поведения можно избежать путем превращения лямбда-выражения в функцию, зависящую только от ее аргументов. Ключевой параметр хранит текущее значение, которое связывается с ним. Вызов функции не должен быть изменен:
funcs = []
for k in range(10):
funcs.append( lambda k = k: k)
>>> funcs[0]()
0
>>> funcs[7]()
7
Тернарный оператор
>>> 'ham' if True else 'spam'
'ham'
>>> 'ham' if False else 'spam'
'spam'
Это было добавлено в 2,5, до которого Вы могли использовать:
>>> True and 'ham' or 'spam'
'ham'
>>> False and 'ham' or 'spam'
'spam'
Однако, если бы значения Вы хотите работать с, считался бы ложью, существует различие:
>>> [] if True else 'spam'
[]
>>> True and [] or 'spam'
'spam'
Заставляют Python regex дерево синтаксического анализа отлаживать Ваш regex.
Регулярные выражения являются замечательной особенностью Python, но отладка их может быть болью, и слишком легко понять regex превратно.
, К счастью, 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]
.
, Конечно, можно объединить его с любыми флагами, которые Вы хотите, как прокомментированный regexes:
>>> 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)
менеджеры по Контексту и" with
" Оператор
, Представленный в PEP 343, , менеджер по контексту является объектом, который действует как контекст во время выполнения для комплекта операторов.
, Так как функция использует новые ключевые слова, она постепенно представляется: это доступно в Python 2.5 через __future__
директива. Python 2.6 и выше (включая Python 3) имеет его в наличии по умолчанию.
я использовал "с" оператором много, потому что я думаю, что это - очень полезная конструкция, вот быстрая демонстрация:
from __future__ import with_statement
with open('foo.txt', 'w') as f:
f.write('hello!')
то, Что происходит здесь негласно, то, что "с" оператором называет специальное предложение __enter__
и __exit__
методы на объекте файла. Детали исключения также передаются __exit__
, если какое-либо исключение было повышено от с телом оператора, позволив, чтобы обработка исключений произошла там.
то, Что это делает для Вас в данном случае, - то, что это гарантирует, что файл закрывается, когда выполнение падает из объема with
комплект, независимо если это обычно происходит или было ли исключение выдано. Это - в основном способ абстрагировать далеко общий код обработки исключений.
Другие случаи общего использования для этого включают блокировку с потоками и транзакции базы данных.
Они - волшебство позади целого набора базовых функций Python.
при использовании отмеченного точкой доступа для поиска участника (например, x.y), Python сначала ищет участника в словаре экземпляра. Если это не найдено, это ищет его в словаре класса. Если это находит его в словаре класса, и объект реализует протокол дескриптора, вместо того, чтобы просто возвратить его, Python выполняет его. Дескриптор является любым классом, который реализует __get__
, __set__
, или __delete__
методы.
Вот то, как Вы реализовали бы свою собственную версию (только для чтения) свойства с помощью дескрипторов:
class Property(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, type):
if obj is None:
return self
return self.fget(obj)
и Вы использовали бы его точно так же, как встроенное свойство ():
class MyClass(object):
@Property
def foo(self):
return "Foo!"
Дескрипторы используются в Python для реализации свойств, связанных методов, статических методов, методов класса и слотов, среди других вещей. Понимание их облегчает видеть, почему большим количеством вещей, которые ранее были похожи на Python 'причуды', является способ, которым они.
Raymond Hettinger имеет превосходное учебное руководство , которое делает намного лучшее задание описания их, чем я.
Можно создать словарь от ряда длины 2 последовательности. Чрезвычайно удобный, когда у Вас есть список значений и список массивов.
>>> dict([ ('foo','bar'),('a',1),('b',2) ])
{'a': 1, 'b': 2, 'foo': 'bar'}
>>> names = ['Bob', 'Marie', 'Alice']
>>> ages = [23, 27, 36]
>>> dict(zip(names, ages))
{'Alice': 36, 'Bob': 23, 'Marie': 27}
разархивировали ненужный в Python
, который Кто-то занес в блог о Python, не имеющем разархивировать функцию для движения с zip (). разархивируйте просто для вычисления потому что:
>>> t1 = (0,1,2,3)
>>> t2 = (7,6,5,4)
>>> [t1,t2] == zip(*zip(t1,t2))
True
На отражении, хотя, у меня было бы явное, разархивировали ().
Чередование if
и for
в пониманиях списка
>>> [(x, y) for x in range(4) if x % 2 == 1 for y in range(4)]
[(1, 0), (1, 1), (1, 2), (1, 3), (3, 0), (3, 1), (3, 2), (3, 3)]
я никогда не понимал это, пока я не изучил Haskell.
можно сослаться на понимание списка, поскольку оно создается символом '_ [1]'. Например, следующая функция, уникальная-ifies список элементов, не изменяя их порядок путем ссылки на его понимание списка.
def unique(my_list):
return [x for x in my_list if x not in locals()['_[1]']]
Метаклассы
, конечно:-) , Что такое метакласс в Python?
понимания Списка
Сравнивают более традиционное (без понимания списка):
foo = []
for x in xrange(10):
if x % 2 == 0:
foo.append(x)
к:
foo = [x for x in xrange(10) if x % 2 == 0]
Первоклассность всего ('все - объект') и погром это может вызвать.
>>> x = 5
>>> y = 10
>>>
>>> def sq(x):
... return x * x
...
>>> def plus(x):
... return x + x
...
>>> (sq,plus)[y>x](y)
20
последняя строка создает кортеж, содержащий две функции, затем оценивает y> x (Верный) и использование что как индекс к кортежу (путем кастинга его к интервалу, 1), и затем вызывает ту функцию с параметром y и показывает результат.
Для дальнейшего злоупотребления при возврате объекта с индексом (например, список) Вы могли бы добавить дальнейшие квадратные скобки на конце; если содержание было вызываемым, больше круглых скобок, и так далее. Для дополнительного извращения используйте результат кода как это как выражение в другом примере (т.е. замените y> x с этим кодом):
(sq,plus)[y>x](y)[4](x)
Это демонстрирует два фасета Python - 'все - объектная' философия, взятая до крайности, и методы, которыми неподходящее или плохо задуманное использование синтаксиса языка может привести к абсолютно нечитабельному, неудобному в сопровождении запутанному коду, который помещается в отдельное выражение.
Кортеж, распаковывающий в для циклов, перечислите выражения генератора и понимания:
>>> l=[(1,2),(3,4)]
>>> [a+b for a,b in l ]
[3,7]
Полезный в этой идиоме для итерации по (ключ, данные) пары в словарях:
d = { 'x':'y', 'f':'e'}
for name, value in d.items(): # one can also use iteritems()
print "name:%s, value:%s" % (name,value)
печать:
name:x, value:y
name:f, value:e
Можно переопределить mro класса с метаклассом
>>> class A(object):
... def a_method(self):
... print("A")
...
>>> class B(object):
... def b_method(self):
... print("B")
...
>>> class MROMagicMeta(type):
... def mro(cls):
... return (cls, B, object)
...
>>> class C(A, metaclass=MROMagicMeta):
... def c_method(self):
... print("C")
...
>>> cls = C()
>>> cls.c_method()
C
>>> cls.a_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(<class '__main__.A'>,)
>>> type(cls).__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
, Он, вероятно, скрыт на серьезном основании.:)
дзэн Python
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
reversed()
встроенный. Это делает итерацию намного более чистого во многих случаях.
быстрый пример:
for i in reversed([1, 2, 3]):
print(i)
производит:
3
2
1
Однако reversed()
также работы с произвольными итераторами, такими как строки в файле или выражения генератора.
интерпретатор в интерпретаторе
стандартная библиотека код модуль позволяет нам, Вы включаете свой собственный read-eval-print цикл в программе или выполняете целый вложенный интерпретатор. Например, (скопировал мой пример от здесь )
$ python
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> shared_var = "Set in main console"
>>> import code
>>> ic = code.InteractiveConsole({ 'shared_var': shared_var })
>>> try:
... ic.interact("My custom console banner!")
... except SystemExit, e:
... print "Got SystemExit!"
...
My custom console banner!
>>> shared_var
'Set in main console'
>>> shared_var = "Set in sub-console"
>>> import sys
>>> sys.exit()
Got SystemExit!
>>> shared_var
'Set in main console'
Это чрезвычайно полезно для ситуаций, где Вы хотите принять заданный сценарием вход от пользователя или запросить состояние VM в режиме реального времени.
TurboGears использует это для большого эффекта при наличии WebConsole, от которого можно запросить состояние Вас живое веб-приложение.
Оператор, перегружающийся для set
встроенный:
>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}
[еще 114] деталь из стандартного справочного руководства по библиотеке: Типы Набора
Python имеет GOTO
..., и это реализовано внешний модуль чистого Python :)
from goto import goto, label
for i in range(1, 10):
for j in range(1, 20):
for k in range(1, 30):
print i, j, k
if k == 3:
goto .end # breaking out from a deeply nested loop
label .end
print "Finished"
pdb — Отладчик Python
Как программист, одной из первых вещей, в которых Вы нуждаетесь для серьезной разработки программы, является отладчик. Python имеет одно встроенное, которое доступно как модуль, названный pdb (для "Отладчика Python", естественно!).
осматривают , модуль является также замечательной функцией.
Моделирование третичного использования оператора и и или.
и и или операторы в Python возвращают сами объекты, а не булевские переменные. Таким образом:
In [18]: a = True
In [19]: a and 3 or 4
Out[19]: 3
In [20]: a = False
In [21]: a and 3 or 4
Out[21]: 4
Однако Py 2.5, кажется, добавил явный третичный оператор
In [22]: a = 5 if True else '6'
In [23]: a
Out[23]: 5
ну, это работает, если Вы уверены, что Ваш истинный пункт не оценивает ко Лжи. пример:
>>> def foo():
... print "foo"
... return 0
...
>>> def bar():
... print "bar"
... return 1
...
>>> 1 and foo() or bar()
foo
bar
1
Для разбираний в нем Вы имеете только к немного больше:
>>> (1 and [foo()] or [bar()])[0]
foo
0
Однако это не столь симпатично. если Ваша версия Python поддерживает его, используйте условный оператор.
>>> foo() if True or bar()
foo
0