Python: легко и просто.
Красиво решаем повседневные задачи.
Александр Семенюк
a_semianiuk@wargaming.net
Python делает всё, чтобы упростить вашу жизнь.
Этот язык предоставляет многообразие инструментов,
позволяющих легко решать многие задачи.
if len(mylist) == 0:
raise Exception('Empty list is not acceptable')
>>> bool( 0 )
False
>>> bool( [] )
False
>>> bool( {} )
False
>>> bool( None )
False
>>> bool( '' )
False
if mylist:
raise Exception('Empty list is not acceptable')
class Basket(object):
empty = True
items = []
def __nonzero__(self):
return not self.empty
def __len__(self):
return len(self.items)
basket = Basket()
print bool(basket) # False
if mylist == None:
do_something()
if mylist == None:
do_something()
if mylist is None:
do_something()
$ python -m timeit -s "x = None" "x is None"
10000000 loops, best of 3: 0.0329 usec per loop
$ python -m timeit -s "x = None" "x == None"
10000000 loops, best of 3: 0.0607 usec per loop
• Всё в Python – это объект.
• Каждая переменная – ссылка на объект.
• Оператор is сравнивает эти ссылки.
class A:
pass
a = A()
b = a
print a is b
print id(a)
print id(b)
True
33274616
33274616
• В Python есть неизменяемые объекты. Их значение не меняется
после создания:
• Числа - 0, 245, 10000000000000001
• Строки - 'Hi people!'
• Кортежи (неизменяемые списки) - (1,2, 'a')
• И, конечно же, None !
if mylist:
raise Exception('Empty list is not acceptable')
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
…
class EmptyListError(Exception):
pass
if not mylist:
raise EmptyListError('Empty list is not acceptable')
try:
work_with_list([])
except EmptyListError:
# we know what's wrong
try:
work_with_list([])
except Exception:
# what to do?
• Python знает, где истина.
• ‘is None’ лучше, чем ‘== None’.
• Всё объект!
• Создавать свои собственные исключения круто.
try:
f = open('config.txt')
line = f.readline()
while line:
line = line.strip(' n')
if not line:
continue
if line.startswith('#'):
continue
do_some_staff(line)
line = f.readline()
finally:
f.close()
for i in range(len(mylist)):
print mylist[i]
for i in range(len(mylist)):
print mylist[i]
for item in mylist:
print item
import itertools
for i in itertools.count():
print i
for item in reversed(mylist):
print item
for item in reversed(mylist):
print item
>>> mylist = [1,2,3]
>>> mylist[::-1]
[3, 2, 1]
$ python -m timeit -s "l = [1, 2, 3]" "list(reversed(l))"
1000000 loops, best of 3: 0.995 usec per loop
$ python -m timeit -s "l = [1, 2, 3]" "l[::-1]"
1000000 loops, best of 3: 0.202 usec per loop
$ python -m timeit -s "l = [1, 2, 3]" "for i in reversed(l): pass"
1000000 loops, best of 3: 0.28 usec per loop
$ python -m timeit -s "l = [1, 2, 3]" "for i in l[::-1]: pass"
1000000 loops, best of 3: 0.318 usec per loop
heroes = ['Batman', 'Spiderman', 'Hulk', 'Invisible Woman']
colors = ['black', 'red', 'green']
for i in range(min(len(heroes), len(colors)):
print list1[i], 'is', list2[i]
for hero, color in zip(heroes, colors):
print hero, 'is', color
heroes_with_colors = dict(zip(heroes, colors))
print heroes_with_colors
{
'Spiderman': 'red',
'Batman': 'black',
'Hulk': 'green'
}
from itertools import izip
for hero, color in izip(heroes, colors):
print hero, 'is', color
>>> for i in 'python': i
...
'p'
'y'
't'
'h'
'o'
'n'
>>> for i in 'python': i
...
'p'
'y'
't'
'h'
'o'
'n'
>>> for key in heroes_with_colors: key
...
'Spiderman'
'Batman'
'Hulk'
>>> for i in 'python': i
...
'p'
'y'
't'
'h'
'o'
'n'
>>> for key in heroes_with_colors: key
...
'Spiderman'
'Batman'
'Hulk'
>>> import re
>>> for match in re.finditer(pattern, string):
... # each match in the string
...
>>> for line in myfile:
... print repr(line) # each line in a file
...
f = open('config.txt')
try:
for line in f:
line = line.strip(' n')
if not line:
continue
if line.startswith('#'):
continue
do_some_staff(line)
finally:
f.close()
def iterate_lines(f):
for line in f:
line = line.strip(' n')
if not line:
continue
if line.startswith('#'):
continue
yield line
f = open('config.txt')
try:
for line in iterate_lines(f):
do_some_staff(line)
finally:
f.close()
>>> mylist
['a', 'b', 'b', 'c']
>>> for index, item in enumerate(mylist):
... if item == 'b':
... del mylist[index]
...
>>> mylist
['a', 'b', 'c']
>>> mydict
{'b': 2}
>>> for key in mydict:
... if key == 'b':
... del mydict[key]
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
>>> for key in mydict.keys():
... if key == 'b':
... del mydict[key]
...
>>> mydict
{}
f = open('config.txt')
try:
for line in iterate_lines(f):
do_some_staff(line)
finally:
f.close()
with EXPR as VAR:
BLOCK
with open('config.txt') as f:
process_file(f)
try:
dangerous_actions()
except AttributeError:
pass # we don't care
from contextlib import contextmanager
@contextmanager
def ignore_errors(*errors):
try:
yield
except errors:
pass
>>> with ignore_errors(KeyError, AttributeError):
... raise KeyError
...
>>>
with open('config.txt') as f:
for line in iterate_lines(f):
do_some_staff(line)
• Итерируйтесь правильно
• Отделяйте административную логику от бизнес логики
• Не изменяйте список, по которому итерируетесь
• Контекстные менеджеры молодцы
Большое спасибо за внимание!

Python легко и просто. Красиво решаем повседневные задачи

  • 2.
    Python: легко ипросто. Красиво решаем повседневные задачи. Александр Семенюк a_semianiuk@wargaming.net
  • 3.
    Python делает всё,чтобы упростить вашу жизнь. Этот язык предоставляет многообразие инструментов, позволяющих легко решать многие задачи.
  • 4.
    if len(mylist) ==0: raise Exception('Empty list is not acceptable')
  • 5.
    >>> bool( 0) False >>> bool( [] ) False >>> bool( {} ) False >>> bool( None ) False >>> bool( '' ) False
  • 6.
    if mylist: raise Exception('Emptylist is not acceptable')
  • 7.
    class Basket(object): empty =True items = [] def __nonzero__(self): return not self.empty def __len__(self): return len(self.items) basket = Basket() print bool(basket) # False
  • 8.
    if mylist ==None: do_something()
  • 9.
    if mylist ==None: do_something() if mylist is None: do_something()
  • 10.
    $ python -mtimeit -s "x = None" "x is None" 10000000 loops, best of 3: 0.0329 usec per loop $ python -m timeit -s "x = None" "x == None" 10000000 loops, best of 3: 0.0607 usec per loop
  • 11.
    • Всё вPython – это объект. • Каждая переменная – ссылка на объект. • Оператор is сравнивает эти ссылки. class A: pass a = A() b = a print a is b print id(a) print id(b) True 33274616 33274616
  • 12.
    • В Pythonесть неизменяемые объекты. Их значение не меняется после создания: • Числа - 0, 245, 10000000000000001 • Строки - 'Hi people!' • Кортежи (неизменяемые списки) - (1,2, 'a') • И, конечно же, None !
  • 13.
    if mylist: raise Exception('Emptylist is not acceptable')
  • 14.
    BaseException +-- SystemExit +-- KeyboardInterrupt +--GeneratorExit +-- Exception +-- StopIteration +-- StandardError | +-- BufferError | +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError …
  • 15.
    class EmptyListError(Exception): pass if notmylist: raise EmptyListError('Empty list is not acceptable')
  • 16.
    try: work_with_list([]) except EmptyListError: # weknow what's wrong try: work_with_list([]) except Exception: # what to do?
  • 17.
    • Python знает,где истина. • ‘is None’ лучше, чем ‘== None’. • Всё объект! • Создавать свои собственные исключения круто.
  • 18.
    try: f = open('config.txt') line= f.readline() while line: line = line.strip(' n') if not line: continue if line.startswith('#'): continue do_some_staff(line) line = f.readline() finally: f.close()
  • 19.
    for i inrange(len(mylist)): print mylist[i]
  • 20.
    for i inrange(len(mylist)): print mylist[i] for item in mylist: print item
  • 21.
    import itertools for iin itertools.count(): print i
  • 22.
    for item inreversed(mylist): print item
  • 23.
    for item inreversed(mylist): print item >>> mylist = [1,2,3] >>> mylist[::-1] [3, 2, 1]
  • 24.
    $ python -mtimeit -s "l = [1, 2, 3]" "list(reversed(l))" 1000000 loops, best of 3: 0.995 usec per loop $ python -m timeit -s "l = [1, 2, 3]" "l[::-1]" 1000000 loops, best of 3: 0.202 usec per loop
  • 25.
    $ python -mtimeit -s "l = [1, 2, 3]" "for i in reversed(l): pass" 1000000 loops, best of 3: 0.28 usec per loop $ python -m timeit -s "l = [1, 2, 3]" "for i in l[::-1]: pass" 1000000 loops, best of 3: 0.318 usec per loop
  • 26.
    heroes = ['Batman','Spiderman', 'Hulk', 'Invisible Woman'] colors = ['black', 'red', 'green'] for i in range(min(len(heroes), len(colors)): print list1[i], 'is', list2[i]
  • 27.
    for hero, colorin zip(heroes, colors): print hero, 'is', color
  • 28.
    heroes_with_colors = dict(zip(heroes,colors)) print heroes_with_colors { 'Spiderman': 'red', 'Batman': 'black', 'Hulk': 'green' }
  • 29.
    from itertools importizip for hero, color in izip(heroes, colors): print hero, 'is', color
  • 30.
    >>> for iin 'python': i ... 'p' 'y' 't' 'h' 'o' 'n'
  • 31.
    >>> for iin 'python': i ... 'p' 'y' 't' 'h' 'o' 'n' >>> for key in heroes_with_colors: key ... 'Spiderman' 'Batman' 'Hulk'
  • 32.
    >>> for iin 'python': i ... 'p' 'y' 't' 'h' 'o' 'n' >>> for key in heroes_with_colors: key ... 'Spiderman' 'Batman' 'Hulk' >>> import re >>> for match in re.finditer(pattern, string): ... # each match in the string ...
  • 33.
    >>> for linein myfile: ... print repr(line) # each line in a file ...
  • 34.
    f = open('config.txt') try: forline in f: line = line.strip(' n') if not line: continue if line.startswith('#'): continue do_some_staff(line) finally: f.close()
  • 35.
    def iterate_lines(f): for linein f: line = line.strip(' n') if not line: continue if line.startswith('#'): continue yield line
  • 36.
    f = open('config.txt') try: forline in iterate_lines(f): do_some_staff(line) finally: f.close()
  • 37.
    >>> mylist ['a', 'b','b', 'c'] >>> for index, item in enumerate(mylist): ... if item == 'b': ... del mylist[index] ... >>> mylist ['a', 'b', 'c']
  • 38.
    >>> mydict {'b': 2} >>>for key in mydict: ... if key == 'b': ... del mydict[key] ... Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: dictionary changed size during iteration
  • 39.
    >>> for keyin mydict.keys(): ... if key == 'b': ... del mydict[key] ... >>> mydict {}
  • 40.
    f = open('config.txt') try: forline in iterate_lines(f): do_some_staff(line) finally: f.close()
  • 41.
    with EXPR asVAR: BLOCK
  • 42.
    with open('config.txt') asf: process_file(f)
  • 43.
  • 44.
    from contextlib importcontextmanager @contextmanager def ignore_errors(*errors): try: yield except errors: pass
  • 45.
    >>> with ignore_errors(KeyError,AttributeError): ... raise KeyError ... >>>
  • 46.
    with open('config.txt') asf: for line in iterate_lines(f): do_some_staff(line)
  • 47.
    • Итерируйтесь правильно •Отделяйте административную логику от бизнес логики • Не изменяйте список, по которому итерируетесь • Контекстные менеджеры молодцы
  • 48.