Поскольку язык программирования Go не поддерживает в настоящее время общие типы, это будет трудно сделать.
В какой-то момент вполне могут быть добавлены дженерики. Мы не чувствуем для них неотложности, хотя мы понимаем, что некоторые программисты это делают.
Дженерики удобны, но они сложны по сложности в системе типов и времени выполнения. Мы еще не нашли дизайн, который дает ценность, пропорциональную сложности, хотя мы продолжаем думать об этом. Между тем, встроенные карты и фрагменты Go, а также возможность использования пустого интерфейса для создания контейнеров (с явным распаковкой) означают, что во многих случаях можно написать код, который будет делать какие дженерики будут разрешены, если будет менее плавным.
Это остается открытой проблемой.
blockquote>Посмотрите на пакет сортировки Go , чтобы увидеть, как он обрабатывает сравнения и другие операции, относящиеся к типу, путем определения sort.Interface с методами Len, Less и Swap.
>>> 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
, но с меньшим количеством ввода и каждым термином только оценен однажды.
Использование в своих интересах динамического характера Python для имения файлов конфигурации приложений в синтаксисе Python. Например, если у Вас было следующее в файле конфигурации:
{
"name1": "value1",
"name2": "value2"
}
Тогда Вы могли тривиально считать его как:
config = eval(open("filename").read())
При использовании дескрипторов на классах, 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()
чистым.
Встроенные методы или функции не реализуют протокол дескриптора, который лишает возможности делать материал как это:
>>> 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
элементы Словаря Доступа как атрибуты (свойства). таким образом, если 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
Объекты в булевом контексте
Пустые кортежи, списки, 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
Интерактивное заполнение клавишей 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.
__ 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. Любые ошибки будут диспетчеризироваться веб-сервисом и пасоваться назад пользователю.
параметр вложенной функции, снова переплетающий
def create_printers(n):
for i in xrange(n):
def printer(i=i): # Doesn't work without the i=i
print i
yield printer
Вложенные понимания списка и выражения генератора:
[(i,j) for i in range(3) for j in range(i) ]
((i,j) for i in range(4) for j in range(i) )
Они могут заменить огромные блоки кода вложенного цикла.
>>> 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]']" "секретное название" создаваемого списка. Очень полезный, когда состояние списка, создаваемого влияние последующие решения сборки.
При отладке сложных структур данных печать модуль прибывает удобный.
Заключение в кавычки из документов..
>>> 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']
Все динамично
"Нет никакого времени компиляции". Все в Python - время выполнения. Модуль 'определяется' путем выполнения источника модуля, от начала до конца, точно так же, как сценарий, и получающееся пространство имен является пространством атрибута модуля. Аналогично, класс 'определяется' путем выполнения тела класса, от начала до конца, и получающееся пространство имен является пространством атрибута класса. Тело класса может содержать абсолютно произвольный код - включая операторов импорта, циклы и другие операторы класса. При создании класса функционируйте или даже модуль 'динамично', относительно как иногда просят, не твердо; на самом деле невозможно избежать, так как все 'динамично'.
Переповышение исключений :
# 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' модулем.
Python совершенствовался, операция разрезания имеет едва известный элемент синтаксиса, замещающий знак:
>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)
, К сожалению, это едва полезно, поскольку замещающий знак только поддерживается, если кортежи включены.
Можно использовать свойство для создания интерфейсов класса более строгими.
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
, Чтобы узнать больше, как работы свойства относятся к дескрипторы .
Встроенный 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'
Отрицательный раунд
round()
функция округляет число плавающее к данной точности в десятичных цифрах, но точность может быть отрицательной:
>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'
Примечание: round()
всегда возвраты плавание, str()
используемый в вышеупомянутом примере, потому что математические операции с плавающей точкой неточны, и под 2.x, второй пример может распечатать как 1234.5700000000001
. Также посмотрите decimal
модуль.
Многие люди не знают о функции "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.
Передающие значения в функции генератора . Например, наличие этой функции:
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
Для добавления большего количества модулей Python (espcially сторонние) большинство людей, кажется, использует переменные среды PYTHONPATH, или они добавляют символьные ссылки или каталоги в их каталогах пакетов сайта. Иначе, должен использовать *.pth файлы. Вот официальное объяснение документа Python:
"Наиболее удобный способ [для изменения пути поиска Python] состоит в том, чтобы добавить конфигурационный файл пути к каталогу, это уже находится на пути Python, обычно к.../site-packages/каталог. Конфигурационные файлы пути имеют расширение .pth, и каждая строка должна содержать единственный путь, который будет добавлен к sys.path. (Поскольку новые пути добавляются к sys.path, модули в добавленных каталогах не переопределят стандартные модули. Это означает, что Вы не можете использовать этот механизм для установки исправленных версий стандартных модулей.)"
Если Вам не нравится использовать пробел для обозначения объемов, можно использовать C-стиль {} путем издания:
from __future__ import braces
Способность заменить даже вещами как удаление файла, файл, открывающийся и т.д. - непосредственное управление библиотекой языка. Это - огромное преимущество когда тестирование. Вы не должны обертывать все в сложные контейнеры. Просто замените функцией/методом и пойдите. Это также называют исправление обезьяны.
Если Вы используете 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
Можно легко транспонировать массив с zip.
a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]
проход () может взять вызываемый аргумент
, Например:
def seek_next_line(f):
for c in iter(lambda: f.read(1),'\n'):
pass
Эти iter(callable, until_value)
функция неоднократно называет callable
и приводит к своему результату, пока until_value
не возвращается.
, Вероятно, легко пропущенный встроенный 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
Аргумент шага в операторах части. Например:
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]