Нужно использовать модуль httplib :
import httplib, sys, time
qs = "First=Josephine&MI=Q&Last=Public"
httpobj = httplib.HTTP('www.some-server.out-there', 80)
httpobj.putrequest('POST', '/cgi-bin/some-cgi-script')
httpobj.putheader('Accept', '*/*')
httpobj.putheader('Connection', 'Keep-Alive')
httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')
httpobj.putheader('Content-length', '%d' % len(qs))
httpobj.endheaders()
httpobj.send(qs)
reply, msg, hdrs = httpobj.getreply()
if reply != 200:sys.stdout.write(httpobj.getfile().read())
Модуль - это файл с расширением .py . Имя файла является именем модуля .
Для импорта этого модуля нужно :
import module_name
Для обращения к методам модуля :
module_name.method()
Модуль может содержать как методы , так и выполняемый код вне методов , который будет выполняться один раз ,
при загрузке модуля .
Для импорта части методов модуля :
from module_name import method1 , method2
Для загрузки модуля с аргументами в нем должна быть функция main :
python module_name arg1
if __name__ == "__main__":
import sys
method3(int(sys.argv[1]))
Функция dir() без аргументов выведет имена всех переменных и методов , определенных в текущем модуле .
num_strings = ['1','21','53','84','50','66','7','38','9']
num = []
n = len(num_strings)
for i in range(0,n):
num.append(int(num_strings[i]))
print num
List=[1,5,4,6,7,2,1,2,3,5,7,6]
print List
List.sort()
last = List[-1]
for i in range(len(List)-2, -1, -1):
if last==List[i]: del List[i]
else: last=List[i]
print List
a = [66.25, 333, 333, 1, 1234.5]
Найти индекс элемента :
a.index(1234.5)
Добавить:
a.insert(2, -1)
a.append(333)
a.extend([3,4,5]) - отличие extend от append в том , что можно добавлять сразу несколько элементов в конец
Удалить:
a.remove(333) - удаление конкретного элемента
a.pop() - удаление последнего элемента
Реверс , сортировка :
a.reverse()
a.sort()
С помощью del можно удалить как отдельный элемент , так и весь список :
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
filter(function, sequence) - проверяет входящую последовательность и возвращает из нее те элементы ,
для которых функция равна true , например : простые числа в диапазоне от 2 до 25 :
def f(x):
return x % 2 != 0 and x % 3 != 0
x = filter(f, range(2, 25))
map(function, sequence) - для каждого элемента входящей последовательности вычисляется новое значение
и возвращается новая последовательность :
def cube(x):
return x*x*x
x = map(cube, range(1, 11))
reduce(function, sequence) - берутся 2 элемента из входящей последовательности , вычисляется результат ,
затем вычисляется для результата и следующего элемента , и т.д. :
def add(x,y):
return x+y
x = reduce(add, range(1, 4))
Сеты - это коллекция уникальных неупорядоченных immutable элементов .
Это не списки, потому что не позволяют индексирования, и это не мапы,
ибо здесь нет пар ключ-значение.
Используется для проверки уникальности .
Имеет встроенные операции типа union, intersection, difference, symmetric difference.
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
print set(basket)
set(['orange', 'pear', 'apple', 'banana'])
a = set('abracadabra')
b = set('alacazam')
print a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
print b # unique letters in b
print a - b # letters in a but not in b
print a | b # letters in either a or b
print a & b # letters in both a and b
print a ^ b # letters in a or b but not both
Функция может строит словарь , используя пары , хранимые в tuple :
print dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
print dict([(x, x**2) for x in (range(2, 10))])
Использовать словарный метод iteritems() для словаря :
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.iteritems():
print k, v
Использовать метод enumerate() для списков :
x=['11','2222',3,4,5]
for i, v in enumerate(x):
print i, v
Для одновременного прохода по двум спискам используется функция zip():
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print 'What is your %s? It is %s.' % (q, a)
Для прохода списка в обратной последовательности - функция reversed():
for i in reversed(xrange(1,10,2)):
... print i
Для прохода списка в отсортированном порядке - функция sorted():
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print f
Используем генератор :
import os
import fnmatch
def gen_find(filepat,top):
for path, dirlist, filelist in os.walk(top):
for name in fnmatch.filter(filelist,filepat):
yield os.path.join(path,name)
pyfiles = gen_find("*.py","./")
for name in pyfiles:
print name
В качестве стека : последний вошел - первый вышел
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
stack.pop()
7
stack
[3, 4, 5, 6]
В качестве очереди : первым вошел - первым вышел
from collections import deque
queue = deque([1,2,3])
queue.append(4)
queue.append(5)
queue.popleft()
queue
[2,3,4,5]
Большие куски кода можно тестировать на производительность с помощью модулей profile и pstats.
Производительность кода можно тестировать с помощью модуля Timer :
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.57535828626024577
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.54962537085770791
Первый вариант с традиционным свопом , как показывает тест , идет медленнее ,
нежели во втором варианте , в котором за кадром остается временное создание tuple .
Нужно использовать модуль threading , стартовать поток , а потом можно вызвать джойн ,
чтобы дождаться его завершения .
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print 'Finished background zip of: ', self.infile
background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
background.join() # ждем , пока поток финиширует
Похож на список , с более быстрым добавлением и извлечением - позволяет извлекать
элементы не только с конца, но и с начала :
from collections import deque
d = deque(["task1", "task2", "task3"])
d.append("task4")
d.popleft()
(["task2", "task3", "task4"])
d.pop()
(["task2", "task3"])
Он манипулирует списками в порядке сортировки .
Например , вставить в нужную позицию элемент в отсортированный список :
import bisect
scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
bisect.insort(scores, (300, 'ruby'))
[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]
Поиск:
L=[4,6,2,7,3,9,6,8]
L.sort()
print bisect.bisect_left(L,7)
print L
Используется принцип бинарного поиска.
Модуль re реализует поддержку регулярных выражений в питоне .
Главнейшая функция этого модуля :
re.search(pattern, string, flags=0)
где pattern - регулярное выражение
string - поисковая строка
flags - флаги для использования модификаторов
Пример : в поисковой строке out ищется шаблон типа даты часы:минуты:секунды: 20:12:06 - hh:mm:ss
find_duration = re.search('[0-9]{2}:[0-9]{2}:[0-9]{2}', out)
if find_duration:
duration = find_duration.group(0)
hours = int(duration[0:2])
minutes = int(duration[3:5])
seconds = int(duration[6:8])
Для замены используется функция sub :
sub(pattern, repl, string, max=0)
pattern - поисковый шаблон
repl - строка , заменяющая найденный шаблон
string - исходня строка
Пример : имеется номер телефона в виде
phone = "2004-959-559"
Нужно убрать тире :
num = re.sub(r'\D', "", phone)
Методы keys() , values() , items() возвращают списки :
ключей
значений
пар ключ-значение
Метод has_key() ищет конкретный ключ
Методы итерации - iterkeys() , itervalues() , iteritems() -
выводят в цикле ключи , значения , пары ключ-значение
d = {1:11,2:22,3:33,4:44,5:55}
print d.keys()
print d.values()
print d.items()
print d.has_key(1)
for i in d.iterkeys():
print i
for i in d.itervalues():
print i
for i in d.iteritems():
print i
clear() - очищает словарь
dict1.update(dict2) - обьединяет 2 словаря , при совпадении ключей , заменяет на dict2.value
get() - возвращает значение по ключу либо None
popitem() - удаляет последнюю пару ключ-значение
pop() - удаляет пару по ключу
setdefault(key,value) - аналогичен get , но добавляет пару , если ее нет в словаре
a = {1:11,2:22,3:33,4:44,5:55}
b = {6:66,7:77,8:88,9:99}
a.update(b)
print a
print b
print a.get(1)
print a.get(11)
a.popitem()
print a
a.pop(7)
print a
sys - переменные окружения и интерпретатора , командная строка , потоки ввода-вывода
string - константы и переменные для работы со строками
os - интерфейс работы с операционной системой
re - регулярные выражения
socket, cgi, urllib, email, http - работа с интернетом
math,time,datetime,thread,queue - другие стандартные модули
find - находит подстроку в строке , возвращает индекс вхождения
title = "Monty Python's Flying Circus"
title.find('Python')
join - обьединяет элементы списка в строку с помощью разделителя
seq = ['1', '2', '3', '4', '5']
sep = '.'
a = sep.join(seq)
print a
1.2.3.4.5
lower() - возвращает строку в нижнем ключе
replace(src,dst) - заменяет в строке подстроку src на подстроку dst
my_str = my_str.replace(',',' ')
string.split(str,',') - разбивает строку на список строк , в данном случае в качестве разделителя в строке ищется запятая
string.split() без аргумента в качестве разделителя принимает пробел(-ы) .
strip() - удаляет пробелы в начале и в конце строки
translate(src,symbol) - аналогично replace , но заменяет единичный символ
Используются традиционные tcp-функции bind,listen,accept в питоновской обертке :
Server:
import socket
s = socket.socket()
host = socket.gethostname()
port = 1234
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close()
Client:
import socket
s = socket.socket()
host = socket.gethostname()
port = 1234
s.connect((host, port))
print s.recv(1024)
Нужно создать свой класс для создания протокола обмена данными .
Обьект этого класса будет создан с помощью стандартного класса Factory .
Server:
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory
class MyServer(Protocol):
def connectionMade(self):
print 'Got connection from', self.transport.client
factory = Factory()
factory.protocol = MyServer
reactor.listenTCP(1234, factory)
reactor.run()
Client:
from twisted.internet import reactor, protocol
from twisted.internet.protocol import ClientFactory, Protocol
class MyClient(Protocol):
def connectionMade(self):
print "Connected to %s." % self.transport.getPeer( ).host
client_factory = ClientFactory()
client_factory.protocol = MyClient
reactor.connectTCP('127.0.0.1', 1234,client_factory)
reactor.run( )
Обработчик запросов Handler вызывает различные стандарные методы в зависимости
от клиента . Для чтения используется атрибут self.rfile , для записи - self.wfile .
from SocketServer import TCPServer, StreamRequestHandler
class Handler(StreamRequestHandler):
def handle(self):
addr = self.request.getpeername()
print 'Got connection from', addr
self.wfile.write('Thank you for connecting')
server = TCPServer(('', 1234), Handler)
server.serve_forever()
1. Booleans : True или False.
2. Numbers : int (1,2...), long(123456789L) , floats (1.1,1.2...), decimal(0.1234567890 , ...) , fractions (1/2,2/3...), комплексные числа.
3. Строки : последовательность Unicode символов
4. Байты
5. Списки : последовательность
6. Tuples : immutable последовательность значений
7. Set : уникальная последовательность
8. Dictionaries : мапы (mappings) пар ключ-значение .
Это обертка для функции или метода класса .
Представляет из себя декларацию непосредственно перед следующей за ней функцией,
которая начинается с символа @.
Пример: пусть у нас имеются несколько функций, возвращающих числа.
Нужно в каждой функции поставить ассерт на случай, если функция возвращает отрицательное число,
сгенерить исключение и вернуть ошибку . Можно было бы добавить в каждую функцию код, проверяющий результат
и генерящий исключение. А если таких функций много ? В этом случае подойдет декоратор :
def check_result(function):
def wrapper(*args,**kargs):
result = function(*args,**kargs)
try:
assert result >=0
print result
except:
print 'error'
result='error'
return result
return wrapper
@check_result
def f1(x,y):
return x-y
@check_result
def f2(x,y):
return y-x
f1(10,5)
f2(10,5)
>>> 5
>>> error
Данный паттерн позволяет создать всего один инстанс .
Используется метод __new__ :
class Singleton(object):
a=1
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
one.a = 3
two = Singleton()
three = Singleton()
print two.a
print three.a
3
3
Это когда несколько переменных ссылаются на один обьект.
Рассмотрим пример:
a = 3
b = a
Две переменных указывают на один и тот же обьект.
a = 4
Создается второй обьект, на который указывает переменная a.
При этом - переменная b по-прежнему указывает на 3.
Другой пример:
L1 = [1,2,3]
L2 = L1
L1 и L2 указывают на один и тот же обьект.
L1 = 24
Будет создан второй обьект , L2 по прежнему будет указывать на список.
Другой пример:
>>> L = [1, 2, 3]
>>> M = [1, 2, 3]
>>> L == M
True
>>> L is M
False
Здесь - два разных обьекта с одинаковыми значениями.
Для перегрузки пользовательского метода в классе в питоне используется двойное подчеркивание,
с которого начинается и заканчивается имя этого метода,
в этом случае будет вызван метод базового класса:
class Base:
def out(self):
print 'Base'
class Derived(Base):
def __out__(self):
print 'Derived'
d=Derived()
d.out()
>>> Base
Полиморфизм в питоне основан на интерфейса , а не типах .
Перегрузить методы можно за счет их списка аргументов:
class C:
def meth(self, x):
...
def meth(self, x, y, z):
...
Фабрика обьектов - это просто функция, генерящая обьекты для классов-
такая функция использует стандартный вызов apply и возвращает инстанс:
def factory(aClass, *args, **kwargs):
print aClass
return apply(aClass, args, kwargs)
class Spam:
def doit(self, message):
print message
class Person:
def __init__(self, name, job):
self.name = name
self.job = job
object1 = factory(Spam)
object2 = factory(Person, "Guido", "guru")
Классическая проблема с множественным наследованием- рассмотрим схему,
когда от базового класса A порождены 2 класса B и C, от которых
в свою очередь порожден класс D:
A
|
---------
| |
B C
---------
|
D
class A: attr = 1
class B(A): pass
class C(A): attr = 2
class D(B,C): pass
x = D( )
print x.attr
>>> 1
Мы вправе были ожидать аттрибут=2, но он перекрывается классом A.
Это классический вариант наследования.
Вот новый стиль - new style - здесь класс C оказывается ниже класса A:
class A(object): attr = 1
class B(A): pass
class C(A): attr = 2
class D(B,C): pass
x = D( )
print x.attr
>>> 2
Статический метод - функция, определенная вне класса и не имеющая атрибута self:
class Spam:
numInstances = 0
def __init__(self):
Spam.numInstances = Spam.numInstances + 1
def printNumInstances( ):
print "Number of instances created: ", Spam.numInstances
a=Spam()
b=Spam()
printNumInstances()
>>> Number of instances created: 2
Статический метод может быть определен и внутри класса - для этого используется
ключевое слово staticmethod - причем метод может быть вызван как статически,
так и через инстанс:
class Multi:
def imeth(self, x):
print self, x
def smeth(x):
print x
def cmeth(cls, x):
print cls, x
smeth = staticmethod(smeth)
cmeth = classmethod(cmeth)
Multi.smeth(3)
>>> 3
obj=Multi()
obj.smeth(5)
>>> 5
Методы класса определяются с помощью ключевого слова classmethod -
здесь автоматически питон передает в качестве первого параметра сам класс - а не инстанс :
Multi.cmeth(7)
>>> 7
obj.cmeth(10)
>>> 10
Находится первый минимум с помощью стандартной функции, удаляется, потом находится второй:
L=[4,6,2,7,3,9,6,8]
print L
smallest = min(L)
min1 = L[smallest]
print min1
L.remove(smallest)
next_smallest = min(L)
min2 = L[next_smallest]
print min2
L.insert(min1, smallest)
print L
Простейшее профилирование кода можно выполнить с помощью модуля time -
в примере измеряется время выполнения в секундах:
import time
L=[4,6,2,7,3,9,6,8,3,4,5,6,67,7,8,8,444,4,5,5,5,55555555,8,87,5,45,4,54,45,45,45]
t1 = time.time()
for i in range(1000000):
L.sort()
L.reverse()
t2 = time.time()
print "\t%.1f" % ((t2 - t1))
Это любой класс, имеющий спец. метод __call__ - при этом обьект можно вызвать как функцию :
Пример - пусть у нас имеется класс Person, имеется коллекция обьектов этого класса - people,
нужно отсортировать эту коллекцию по фамилиям. Для этого можно использовать функтор Sortkey
class SortKey:
def __init__(self, *attribute_names):
self.attribute_names = attribute_names
def __call__(self, instance):
values = []
for attribute_name in self.attribute_names:
values.append(getattr(instance, attribute_name))
return values
class Person:
def __init__(self, forename, surname, email):
self.forename = forename
self.surname = surname
self.email = email
people=[]
p=Person('Petrov','','')
people.append(p)
p=Person('Sidorov','','')
people.append(p)
p=Person(u'Ivanov','','')
people.append(p)
for p in people:
print p.forename
people.sort(key=SortKey("forename")) # вызов функтора SortKey
for p in people:
print p.forename
>>> Ivanov
>>> Petrov
>>> Sidorov
Дескриптор - это класс, который хранит и контролирует атрибуты других классов.
Вообще любой класс, который имплементирует один из специальных методов -
__get__ , __set__ , __delete__ , является дескриптором.
Пример:
class ExternalStorage:
__slots__ = ("attribute_name",)
__storage = {}
def __init__(self, attribute_name):
self.attribute_name = attribute_name
def __set__(self, instance, value):
self.__storage[id(instance), self.attribute_name] = value
def __get__(self, instance, owner=None):
if instance is None:
return self
return self.__storage[id(instance), self.attribute_name]
class Point:
__slots__ = ()
x = ExternalStorage("x")
y = ExternalStorage("y")
def __init__(self, x=0, y=0):
self.x = x
self.y = y
p1=Point(1,2)
p2=Point(3,4)
print p1.x
В данном случае класс Point не имеет собственных атрибутов x,y , хотя вызывает их как будто
они есть - на самом деле они хранятся в дескрипторе ExternalStorage.
В данном примере 2 скрипта - рarent.py и child.py.
Запускается parent.py.
Child.py выступает в роли аргумента command, который передается в запускаемый процесс.
У этого процесса есть стандартный вход, куда мы передаем 2 аргумента - поисковое слово и имя файла.
Запись на стандартный вход осуществляет модуль subprocess.
Каждый процесс пишет результат своего поиска в консоль.
В главном процессе мы ждем, пока все child не закончат свою работу.
Код parent.py:
import os
import subprocess
import sys
child = os.path.join(os.path.dirname(__file__), "./child.py")
word = 'word'
file = ['./file1','./file2']
pipes = []
for i in range(0,2):
command = [sys.executable, child]
pipe = subprocess.Popen(command, stdin=subprocess.PIPE)
pipes.append(pipe)
pipe.stdin.write(word.encode("utf8") + b"\n")
pipe.stdin.write(file[i].encode("utf8") + b"\n")
pipe.stdin.close()
while pipes:
pipe = pipes.pop()
pipe.wait()
Код child.py:
import sys
word = sys.stdin.readline().rstrip()
filename = sys.stdin.readline().rstrip()
try:
with open(filename, "rb") as fh:
while True:
current = fh.readline()
if not current:
break
if (word in current ):
print("find: {0} {1}".format(filename,word))
except :
pass
Чтобы прочитать вывод процесса:
ret = subprocess.call("ls -l", shell=True)
p = subprocess.Popen("ls -l", shell=True, stdout=subprocess.PIPE)
out = p.stdout.read()