Raymond Hettinger:
Transforming Code into Beautiful, Idiomatic Python
A kódot többször olvassuk mint írjuk.
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!>>> from __future__ import braces
File "<ipython-input-2-2aebb3fc8ecf>", line 1
from __future__ import braces
SyntaxError: not a chanceimport jsonfor line in file:
print(line)class Zoo:
...def count_banana():
return 5class Zoo:
@staticmethod
def count_banana():
return 5class PokerRange:
def to_html(self):
"""Returns a 13x13 HTML table representing the hand range.""""""
flask
~~~~~
A microframework based on Werkzeug. It's extensively documented
and follows best practice patterns.
:copyright: (c) 2015 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""__init__.py:
iterable = ['Jóska', 'Pista', 'Sári', 'Mariska']
for val in iterable:
print(val)var iterable = ['Jóska', 'Pista', 'Sári', 'Mariska'];
for (var i = 0; i < iterable.length; i++) {
console.log(iterable[i]);
}
JavaScript
Python
const char *iterable[4];
iterable[0] = "Jóska";
iterable[1] = "Pista";
iterable[2] = "Sári";
iterable[3] = "Mariska";
int i;
for (i = 0; i < 4; i++) {
printf ("%s\n", iterable[i]);
}C
for i in [0, 1, 2, 3, 4, 5]:
print(i**2)for i in range(6):
print(i**2)
# python 2:
for i in xrange(6):
print(i**2)Egyszerű számsor bejárása
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print(colors[i])for color in colors:
print(color)Lista bejárása
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)-1, -1, -1):
print(colors[i])for color in reversed(colors):
print(color)Bejárás visszafelé
i = 0
for color in colors:
print(i, '-->', color)
i += 1for i, color in enumerate(colors):
print(i, '-->', color)colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print(i, '-->', colors[i])Iterálás indexekkel
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue', 'yellow']
n = min(len(names), len(colors))
for i in range(n):
print(names[i], '-->', colors[i])Két collection iterálása egyszerre
for name, color in zip(names, colors):
print(name, '-->', color)
# python 2:
for name, color in izip(names, colors):
print(name, '-->', color)colors = ['red', 'green', 'blue', 'yellow']
for color in sorted(colors):
print(color)for color in sorted(colors, reverse=True):
print(color)Iterálás sorrendben
# python 2.4+
print(sorted(colors, key=len)colors = ['red', 'green', 'blue', 'yellow']
# python <2.4
def compare_length(c1, c2):
if len(c1) < len(c2): return -1
if len(c1) > len(c2): return 1
return 0
print sorted(colors, cmp=compare_length)Iterálás egyedi sorrendben
blocks = []
while True:
block = f.read(32)
if block == '':
break
blocks.append(block)
def read32():
return f.read(32)
blocks = []
for block in iter(read32, ''):
blocks.append(block)from functools import partial
blocks = []
for block in iter(partial(f.read, 32), ''):
blocks.append(block)Függvény hívása bizonyos pontig (sentinel value)
def find(seq, target):
found = False
for i, value in enumerate(seq):
if value == target:
found = True
break
if not found:
return -1
return idef find(seq, target):
for i, value in enumerate(seq):
if value == target:
break
else: # finished the body
return -1
return idef find(seq, target):
i = -1
for i, value in enumerate(seq):
if value == target:
break
return iTöbb kilépési pont
explicit megkülönböztetése
Dictionary kulcsok bejárása
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print(k)for k in list(d):
if k.startswith('r'):
del d[k]
# Python 2:
for k in d.keys():
if k.startswith('r'):
del d[k]
d = {k: d[k] for k in d if not k.startswith('r')}Dictionary kulcsok és értékek bejárása
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print(k, '-->', d[k])for k, v in d.items():
print(k, '-->', v)
# Python 2:
for k, v in d.iteritems():
print k, '-->', vDictionary létrehozása
default értékkel
errors = dict.fromkeys(['sid', 'wsid', 'base64'], 0)
# {'errors': 0, 'wsid': 0, 'base64: 0}Dictionary létrehozása párokból
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue']
d = dict(zip(names, colors))
# {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
# Python 2:
d = dict(izip(names, colors))
Számlálás dictionary-vel
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
if color not in d:
d[color] = 0
d[color] += 1
# {'blue': 1, 'green': 2, 'red': 3}d = {}
for color in colors:
d[color] = d.get(color, 0) + 1from collections import defaultdict
d = defaultdict(int)
for color in colors:
d[color] += 1Csoportosítás dictionary-vel
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
d = {}
for name in names:
key = len(name)
if key not in d:
d[key] = []
d[key].append(name)
# {5: ['roger', 'betty'], 6: ['rachel', 'judith'],
# 7: ['raymond', 'matthew', 'melissa', 'charlie']}d = {}
for name in names:
key = len(name)
d.setdefault(key, []).append(name)from collections import defaultdict
d = defaultdict(list)
for name in names:
key = len(names)
d[key].append(name)Véletlenszeű elem atomic kinyerése dictionary-ből
names = {'matthew': 'blue', 'rachel': 'green',
'raymond': 'red'}
while d:
key, value = d.popitem()
print(key, '-->', value)Több dictionary összekapcsolása
import os
import argparse
defaults = {'color': 'red', 'user': 'guest'}
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args([])
command_line_args = {k: v for k, v in
vars(namespace).items() if v}
d = defaults.copy()
d.update(os.environ)
d.update(command_line_args)import os
from collections import ChainMap
d = ChainMap(command_line_args, os.environ, defaults)Felsorolás kibontása
p = 'Raymond', 'Hettinger', 0x30, 'python@example.com'
first_name = p[0]
last_name = p[1]
age = p[2]
email = p[3]first_name, last_name, age, email = pTöbb változó változtatása egyszerre
def fibonacci(n):
x = 0
y = 1
for i in range(n):
print(x)
t = y
y = x + y
x = tdef fibonacci(n):
x, y = 0, 1
for i in range(n):
print(x)
x, y = y, x+yEgyszerű list létrehozása
numbers = []
for number in range(10):
numbers.append(number)numbers = [number for number in range(10)]numbers = range(10)dict, set comprehensions
parity = {x: x**2 for x in (2, 4, 6)}
# {2: 4, 4: 16, 6: 36}even_numbers = {num for num in bigdata if num % 2 == 0}results = []
for i in range(10):
s = i ** 2
resul.append(s)
print(sum(result))print(sum([i ** 2 for i in range(10)]))
# Python 2:
print sum([i ** 2 for i in xrange(10)])Számok összeadása
print(sum(i ** 2 for i in range(10)))
# Python 2:
print sum(i ** 2 for i in xrange(10))Dekorátor használata
"adminisztratív logika" szétválasztására
def web_lookup(url, saved({}):
if url in saved:
return saved[url]
page = urllib.urlopen(url).read()
saved[url] = page
return pagefrom functools import lru_cache
@lru_cache
def web_lookup(url):
return urllib.urlopen(url).read()Dekorátor használata
"adminisztratív logika" szétválasztására
from functools import wraps
def lru_cache(func):
saved = {}
@wraps(func)
def newfunc(*args):
if args in saved:
return newfunc(*args)
result = func(*args)
saved[args] = result
return result
return newfuncCommand line példa
@main.command(help='Download ELB logs from S3 bucket. '
'If minute is passed, it will be used, otherwise only hour '
'will be included in prefix.')
@click.argument('wsid', type=ct.WSID)
@click.argument('year', type=ct.YEAR, default='')
@click.argument('month', type=ct.MONTH, default='')
@click.argument('day', type=ct.DAY, default='')
@click.argument('hour', type=ct.HOUR, default='')
@click.argument('minute', type=ct.MINUTE, default='')
@click.pass_context
def download(ctx, wsid, year, month, day, hour, minute):
"""Download ELB logs from S3 bucket."""with open('big_data.txt') as f:
data = f.read()f = open('big_data.txt')
try:
data = f.read()
finally:
f.close()Multi-thread lock
import threading
lock = threading.Lock()
lock.acquire()
try:
print('Critical section 1')
print('Critical section 2')
finally:
lock.release()import threading
lock = threading.Lock()
with lock:
print('Critical section 1')
print('Critical section 2')
Ideiglenes környezet szétválasztása 1.
from decimal import Decimal, getcontext, setcontext
old_context = getcontext().copy()
getcontext().prec = 50
print(Decimal(335) / Decimal(113))
setcontext(old_context)from decimal import Decimal, Context, localcontext
with localcontext(Context(prec=50)):
print(Decimal(355) / Decimal(113))Ideiglenes környezet szétválasztása 2.
with open('pow_help.txt', 'w') as f:
oldstdout = sys.stdout
sys.stdout = f
try:
help(pow)
finally:
sys.stdout = oldstdoutfrom contextlib import redirect_stdout
with open('pow_help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)Hiányzó file probléma
try:
with open('bigdata.txt') as f:
bigdata = f.read().strip()
except FileNotFoundError:
print("File is missing, loading default values")if os.path.exists('bigdata.txt'):
with open('bigdata.txt') as f:
bigdata = f.read().strip()
try:
do_something()
except:
pass
try:
do_something()
except Exception:
pass
try:
do_something()
except Exception as e:
pass
try:
do_something()
except ValueError as e:
handle_exception(e)
try:
read_file()
except FileNotFoundError as e:
handle_exception(e)
Függvényhívás
keyword argumentekkel
twitter_search('@obama', retweets=False,
numtweets=20, popular=True)twitter_search('@obama', False, 20, True)named tuple
doctest.testmod()
TestResults(failed=0, attempted=4)doctest.testmod()
(0, 4)from collections import namedtuple
TestResults = namedtuple('TestResult', ['failed', 'attempted'])Teranry conditional operator
number = count if count % 2 != 0 else count - 1name = user.name() if user is not None else 'Guest'from collections import Counter
colors = ['red', 'green', 'red', 'blue', 'green', 'red', 'red']
colorcount = Counter(colors)
colorcount.most_common()
# [('red', 4), ('green', 2), ('blue', 1)]Egy jobb számláló
with open('/some/file', 'r') as f:
line_count = Counter(f)for text in lines:
if re.search(‘[a-zA-Z]\=’, text):
some_action(text)
elif re.search(‘[a-zA-Z]\s\=’, text):
some_other_action(text)
else:
some_default_action()
Funckionális eszköz: partial
def is_grouped_together(text):
return re.search("[a-zA-Z]\s\=", text)
def is_spaced_apart(text):
return re.search(“[a-zA-Z]\s\=”, text)
def and_so_on(text):
return re.search(“pattern_188364625", text)
...
for text in lines:
if is_grouped_together(text):
some_action(text)
elif is_spaced_apart(text):
some_other_action(text)
else:
some_default_action()def my_search_method():
is_spaced_apart = partial(re.search, '[a-zA-Z]\s\=')
is_grouped_together = partial(re.search, '[a-zA-Z]\=')
...
for text in lines:
if is_grouped_together(text):
some_action(text)
elif is_spaced_apart(text):
some_other_action(text)
else:
some_default_action()
Funckionális eszköz: partial
Stringek összefűzése
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
s = names[0]
for name in names[1:]:
s += ', ' + name
print(s)print(', '.join(names))Beszúrás felsorolás elejére
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
del names[0]
names.pop(0)
names.insert(0, 'mark')from collections import deque
names = deque(['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie'])
del names[0]
names.popleft()
names.appendleft()