в Python значения аргументов функции могут передаваться в

advertisement
в
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)
Download