в Python значения аргументов функции могут передаваться в произвольном порядке, при этом необходимо указывать имена всех аргументов, кроме аргументов, для которых заданы значения по умолчанию: def func(a, b, c, d = 4): return func(c = 3, b = 2, a = 1) в Python есть встроенный тип комплексного числа: -1 - 0j в Python допустимо присваивание набора набору: a, b = b, a (a, b) = (b, a) в Python существует оператор спискового включения, который возвращает список из элементов заданного вида, полученных на всех итерациях цикла (если указаны вложенные циклы, то имеется ввиду цикл наибольшей вложенности), для которых выполняется указанное условие (может быть не указано): print [(i, j) for i in range(3) for j in range(3) if i <= j] << [(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] print range(2), range(3) << [0, 1], [0, 1, 2] в Python доступны следующая встроенная операция доступа к подспискам списка [[n1]:[n2][:[n3]]], которая возвращает список из элементов, начиная с элемента с индексом n1 (0, если не указан) и заканчивая элементом с индексом меньшим n2 (бесконечность, если не указан), при этом индексы берутся через n3 позиции (через 1, если не указан). Отрицательные значения n1 и n2 интерпретируются как смещения влево от индекса последнего элемента списка: s = range(5); print s, s[1], s[1:], s[1:3], s[:2], s[0:3:2], s[0::2], s[::3] << [0, 1, 2, 3, 4] 1 [1, 2, 3, 4] [1, 2] [0, 1] [0, 2] [0, 2, 4] [0, 3] в Python подсписок можно использовать в левой части оператора присваивания, в этом случае выбранные из списка слева элементы заменяются на элементы списка справа. Таким образом можно организовать обычную вставку одного списка в другой. Также можно удалить подсписок, используя универсальный оператор удаления ссылки на объект del, который действует рекурсивно: s[::2] = range(5)[:3]; print s << [0, 1, 1, 3, 2] s[2:2] = [5, 6]; print s << [0, 1, 5, 6, 1, 3, 2] del s[1::2] << [0, 5, 1, 2] в Python строка является списком символов, и к ней применимы все описанные выше операции. в Python есть встроенный тип словаря данных: d = {1: 'one', 2: 'two', 3: 'three', 4: 'four'} d0 = {0: 'zero'} d.update(d0) в Python можно использовать оператор множественного сравнения: a < b < c ... y < z в Python загруженный модуль может быть перезагружен с помощью функции reload(), если файл с его исходным кодом, например, был изменён, при этом существующие экземпляры классов со старой реализацией не изменят своего поведения. в Python присутствует встроенный оператор форматирования строки и доступна позиционная и непозиционная подстановка значений параметров: print "%i + %i = %i" % (1, 2, 3) << 1 + 2 = 3 print "%(c)s = %(b)s + %(a)s" % { 'a': 1, 'b': 2, 'c': 3 } << 3 = 2 + 1 a = 1; b = 2; c = 3 print "%(b)s + %(a)s = %(c)s" % vars() << 2 + 1 = 3 в Python возможно динамическое создание и удаление атрибутов объекта: class A: def __init__(self): self.x = 1 pass a = A() a.attr = 1 del a.attr del a.x в Python возможно объекта: динамическое изменение класса class type1(object): pass class type2(object): pass something = type1() type(something) << <class 'type1'> something.__class__ = type2 type(something) << <class 'type2'> в Python объекты, представленные одинаковыми литералами (строки, числа, кортежи, константные списки), в том числе вычисляемыми к одному литералу на стадии компиляции, хранятся в памяти в единственном экземпляре, в чём можно убедиться с помощью функции id(): print id("string"), id("str" + "ing") << 3082755776, 3082755776 a = "string"; print id(a) << 3082755776 b = "string"; print id(b) << 3082755776 в Python значение по умолчанию аргумента функции является постоянным объектом и его изменение отразится на всех последующих вызовах функции: def mylist(val, lst=[]): lst.append(val) return lst print mylist(1), mylist(2) << [1] [1, 2] def mylist2(val, lst=None): lst = lst or [] lst.append(val) return lst print mylist2(1), mylist2(2) << [1] [2] в Python можно контролировать такие параметры среды исполнения, как максимальную глубину рекурсивных вызовов функции c помощью вызова sys.setrecursionlimit(N). в Python существует оператор apply для осуществления вызова функции, переданной ему вместе со значениями её позиционных и непозиционных параметров через аргументы: lst = [1, 2, 3] print max(lst), apply(max, lst) << 3, 3 def f(a,b): return a * 2 + b print apply(f, [], {"a" : 3, "b" : 4}) << 10 в Python существуют операторы filter для удаления из списка элементов, не удовлетворяющих заданному условию, и оператор zip для слияния нескольких списков в список кортежей: filter(lambda x: x.isalpha(), 'Hi, there! I am eating an apple.') << 'HithereIameatinganapple' print zip(range(5), "abcde") << [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')] в Python существуют оператор lambda для динамического определения функции и оператор map для выполнения заданной функции на кортежах значений аргументов и возвращения списка значений функции (если вместо функции передан None, то результат эквивалентен результату оператора zip): l1 = [2, 7, 5, 3] l2 = [-2, 1, 0, 4] print map(lambda x, y: x+y, l1, l2) << [0, 8, 5, 7] print map(None, l1, l2) << [(2, -2), (7, 1), (5, 0), (3, 4)] в Python доступны не только классические итераторы, но и так называемые генераторы или "ленивые" итераторы, которые позволяют обращаться к значениям, генерируемым некоторой заданной функцией. При каждом обращении к следующему значению функция исполняется в отдельном потоке и исполнение приостанавливается при выдаче в ней очередного значения, при запросе следующего значения функция продолжает работу с точки останова. Итерация по генерируемому ряду чисел Фибоначи: def Fib(N): a, b = 0, 1 for i in xrange(N): yield a a, b = b, a + b for i in Fib(100): print i, "Ленивый" обход дерева: def inorder(t): if t: for x in inorder(t.left): yield x yield t.dat for x in inorder(t.right): yield x С помощью итераторов и оператора спискового включения (генерирующего выражения, если не указано условие) операцию подстановки подстроки в файле можно записать в одну строку: open("output.dat", "w").writelines(l.replace(" - ", " - ") for l in open("input.dat")) в Python существуют оператор кэрринга или подстановки значений произвольного подмножества аргументов функции и дальнейшего её использования как объекта, который можно вызвать как обычную функцию, передав значения остальных аргументов: from functional import curry, Blank def subtract(x, y): return x - y subtract_from_3 = curry(subtract, 3) print subtract_from_3(2) << 1 subtract_2 = curry(subtract, Blank, 2) print subtract_2(3) << 1 # access to class members can not be restricted by qualifiers in class declaration # however members starting with '_' are supposed to be for internal usage only and # with '__' actually can not be accessed outside class, all other are public # how to retrieve methods / attributes of any object / class / module >>> dir(a) ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', ... # type imitation class CountArgs(object): def __call__(self, *args, **kwargs): return len(args) + len(kwargs) cc = CountArgs() print cc(1, 3, 4) # formatting output >>> print ", ".join(["%s" % e for e in range(1, 6)]) 1, 2, 3, 4, 5 # weak references and proxy objects >>> s = MyClass() >>> s1 = weakref.proxy(s) >>> ss = weakref.ref(s) >>> del s >>> print ss() None >>> print s1() ReferenceError: weakly-referenced object no longer exists # overriding type of varriable class A(object): x = 0 class B(A): pass a = A() a = B() # dynamic class generating (class factory) def cls_factory_f(func): class X(object): pass setattr(X, func.__name__, func) return X def my_method(self): print "self:", self My_Class = cls_factory_f(my_method) my_object = My_Class() my_object.my_method() # dynamic class generating from metaclass def my_method(self): print "self:", self My_Class = type('My_Class', (object,), {'my_method': my_method}) # inheriting from metaclass class My_Type(type): def __new__(cls, name, bases, dict): return type.__new__(cls, name, bases, dict) def __init__(cls, name, bases, dict): return super(My_Type, cls).__init__(cls, name, bases, dict) my = My_Type("X", (), {}) # multimethod def m1(a, b): return 'AA' def m2(a, b): return 'AB' g = Generic() g.add_method(Method((A, A), m1)) g.add_method(Method((A, B), m2)) print g(A(), B()) # dynamic class templates def aa(x): class X: def m(self): return x return X # initializing object's base class part (can be anywhere in constructor) class B(list): def __init__(self, *params): print 1 super(B, self).__init__(params) # object properties class CL(object): def set_color(self, value): self.__color = value def del_color(self): del self.__color color = property(lambda self: self.__color, set_color, del_color, "Color property.") # finding minimum element in matrice, every object derived from object has __reduce__ operation >>> a = array([[2, 1], [4, 3]]) >>> print minimum.reduce(minimum.reduce(a)) 1 # applying conditions on array elements >>> a = array([[1, 2], [0, 1]]) >>> def cond(x): >>> return x == 2 >>> print logical_or.reduce(cond(a.flat)) 1 >>> a[1, 1] = 1; print logical_or.reduce(cond(a.flat)) 0 # regular expressions r"(?P<var>\w+)=.*\b(?P=var)\b" # named group r"\bregular(?=\s+expression)". # looking forward, should match 'regular' only if 'expression' follows r"(?<=regular )expression" # looking backward, should match 'expression' only if 'regular' precedes # multiline strings import os print """Content-Type: text/plain %s""" % os.environ # RPC server from SimpleXMLRPCServer import SimpleXMLRPCServer srv = SimpleXMLRPCServer(("localhost", 8000)) srv.register_function(pow) srv.register_function(lambda x,y: x+y, 'add') srv.serve_forever() # RPC client import xmlrpclib req = xmlrpclib.ServerProxy("http://localhost:8000") print req.add(1, 3) # if - else operator IF = lambda a,b,c:(a() and [b()] or [c()])[0] # while operator: while expression(): function() WHILE = lambda e,f:(e() and (f(),WHILE(e,f)) or 0) # for operator: for x in items: f(x) map(f,items)