Sur Youtube, Raymond Hettinger (développeur du noyau python) explique les erreurs courantes et l'écriture correcte en python Vidéo J'ai trouvé? V = OSGv2VnC0go), je vais donc le résumer. Dans la vidéo, j'utilise principalement python2 comme exemple (car c'est une vidéo de 2013), mais ici je l'ai convertie en python3 autant que possible. Maintenant qu'il a peut-être déjà été écrit d'une manière ancienne, veuillez l'utiliser tout en le vérifiant comme il convient.
Loop
Mauvais exemple
for i in [0, 1, 2, 3, 4, 5]:
print(i**2)
Mettez la liste entière en mémoire. ↓
Bon exemple
for i in range(6):
print(i**2)
Puisque «range» est généré un par un en tant qu'itérateur, la mémoire n'est pas gaspillée.
En python2,
range
est une liste etxrange
est un itertor En python3,range
est un itérateur (le nom dexrange
en python2 a changé)
Mauvais exemple
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print(colors[i])
↓
Bon exemple
colors = ['red', 'green', 'blue', 'yellow']
for color in colors:
print(color)
Écrire ci-dessous est plus rapide
Mauvais exemple
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)-1, -1, -1):
print(colors[i])
↓
Bon exemple
colors = ['red', 'green', 'blue', 'yellow']
for color in reversed(colors):
print(color)
Mauvais exemple
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print(i, '--->', colors[i])
↓
Bon exemple
colors = ['red', 'green', 'blue', 'yellow']
for i, color in enumerate(colors):
print(i, '--->', color)
Mauvais exemple
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]
↓
Bon exemple
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue', 'yellow']
for name, color in zip(names, colors):
print(name, '--->', color)
Lorsque des itérateurs de différentes longueurs sont saisis dans le zip, ils seront alignés sur le plus court. ʻItertools.zip_longest` pour s'aligner sur le plus long
En python2,
zip
génère une liste (ʻizipest un itérateur), En python3,
zip` génère un itérateur
Mauvais exemple
colors = ['red', 'green', 'blue', 'yellow']
def compare_length(c1, c2):
if len(c1) < len(c2):
return -1
elif len(c1) > len(c2):
return 1
else:
return 0
print(sorted(colors, cmp=compare_length)
↓
Bon exemple
colors = ['red', 'green', 'blue', 'yellow']
print(sorted(colors, key=len))
** Le tri par clé est-il suffisant? ** ** Dans certains cas, ce n'est pas suffisant, mais dans la plupart des cas, ce n'est pas grave. (SQL fait beaucoup de tri, mais il le fait par tri par clé)
Mauvais exemple
blocks = []
while True:
block = f.read(32)
if block == '':
break
blocks.append(block)
↓
Bon exemple
blocks = []
for block in iter(functool.partial(f.read, 32), ''):
blocks.append(block)
partiel est désagréable, mais le mérite de pouvoir le gérer comme un itérateur est grand Il vaut mieux éviter la valeur sentinelle
Mauvais exemple
def find(seq, target):
found = False
for i, value in enumerate(seq):
if value == target:
found = True
break
if not found:
return -1
return i
Exemple lorsque vous devez utiliser un drapeau (found
)
↓
Bon exemple
def find(seq, target):
for i, value in enumerate(seq):
if value == target:
break
else:
return -1
return i
S'il n'y a pas de pause pour, l'instruction else est exécutée. Il regrette qu'il aurait dû le nommer «nobreak» au lieu d'autre.
Dictionary
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print(k)
↑ Quelque chose d'étrange se produit lorsque vous modifiez le dictionnaire
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d.keys():
if k.startswith('r'):
del d[k]
↑ d.keys ()
fait une copie de la liste à l'avance, vous pouvez donc changer le dictionnaire
Mauvais exemple
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k in d:
print(k, '--->', d[k])
↓
Bon exemple
d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
for k, v in d.items():
print(k, '--->', v)
names = ['raymond', 'rachel', 'matthew']
colors = ['red', 'green', 'blue']
d = dict(zip(names, colors))
Méthode inefficace
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
if color in d:
d[color] = 0
d[color] += 1
↓
Le droit chemin
d = {}
for color in colors:
d[color] = d.get(color, 0) + 1
↓
Méthode récente
d = defaultdict(int)
for color in colors:
d[color] += 1
Mauvais exemple
names = ['raymond', 'raychel', 'matthew', 'roger', 'betty', 'melisa', 'judith', 'charlie']
d = {}
for name in names:
key = len(name)
if key not in d:
d[key] = []
d[key].append(name)
↓
Le droit chemin
d = {}
for name in names:
key = len(name)
d.setdefault(key, []).append(name)
↓
Méthode récente
d = defaultdict(list)
for name in names:
key = len(name)
d[key].append(name)
get
n'affecte pas au dictionnaire. substituts desetdefault
Mauvais exemple
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)
Un grand nombre de dictionnaires sont copiés ↓
Bon exemple
d = collections.ChainMap(command_line_args, os.environ, defaults)
Conservez le dictionnaire original tel quel sans le copier
Mauvais exemple
twitter_search('@obama', False, 20, True)
Je ne comprends pas le sens de l'argument ↓
Bon exemple
twitter_search('@obama', retweets=False, numtweets=20, popular=True)
NamedTuple
Mauvais exemple
> doctest.testmod()
(0, 4)
Je ne comprends pas la signification de 0,4 ↓
Bon exemple
> doctest.testmod()
TestResults(failed=0, attempted=4)
TestResults
est
TestResults = namedtuple('TestResults', ['failed', 'attempted'])
Peut être fait avec
Mauvais exemple
p = 'Raymond', 'Hettinger', 0x30, '[email protected]'
fname = p[0]
lname = p[1]
age = p[2]
email = p[3]
↓
Bon exemple
fname, lname, age, email = p
Mauvais exemple
def fibonacci(n):
x = 0
y = 1
for i in range(n):
print(x)
t = y
y = x + y
x = t
Il y a un moment où l'état s'effondre pendant l'exécution. Facile de se tromper dans l'ordre des lignes ↓
Bon exemple
def fibonacci(n):
x, y = 0, 1
for i in range(n):
print(x)
x, y = y, x+y
C'est plus proche de la pensée humaine.
Mauvais exemple
names = ['raymond', 'raychel', 'matthew', 'roger', 'betty', 'melisa', 'judith', 'charlie']
s = names[0]
for name in names[1:]:
s += ', ' + name
↓
Bon exemple
', '.join(names)
Mauvais exemple
names = ['raymond', 'raychel', 'matthew', 'roger', 'betty', 'melisa', 'judith', 'charlie']
del names[0]
names.pop(0)
names.insert(0, 'mark')
lent ↓
Bon exemple
names = deque(['raymond', 'raychel', 'matthew', 'roger', 'betty', 'melisa', 'judith', 'charlie'])
del names[0]
names.popleft()
names.appendleft('mark')
vite
Mauvais exemple
def web_lookup(url, saved={}):
if url in saved:
return saved[url]
page = urlib.urlopen(url).read()
saved[url] = page
return page
↓
Bon exemple
@lru_cache()
def web_lookup(url):
return urllib.urlopen(url).read()
La logique métier et la logique administrative sont séparées
Mauvais exemple
oldcontext = getcontext().copy()
getcontext().prec = 50
print(Decimal(355) / Decimal(113))
setcontext(oldcontext)
↓
Bon exemple
with localcontext(Context(prec=50)):
print(Decimal(355) / Decimal(113))
Mauvais exemple
f = open('data.txt')
try:
data = f.read()
finally:
f.close()
↓
Bon exemple
with open('data.txt') as f:
data = f.read()
Mauvais exemple
lock = threading.Lock()
lock.acquire()
try:
print('Critical section 1')
print('Critical section 2')
finally:
lock.release()
↓
Bon exemple
lock = threading.Lock()
with lock:
print('Critical section 1')
print('Critical section 2')
Mauvais exemple
try:
os.remove('somefile.tmp')
except OSError:
pass
↓
Bon exemple
with ignored(OSError):
os.remove('somefile.tmp')
Mauvais exemple
with open('help.txt', 'w') as f:
oldstdout = sys.stdout
sys.stdout = f
try:
help(pow)
finally:
sys.stdout = oldstdout
↓
Bon exemple
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
Mauvais exemple
result = []
for i in range(10):
s = i**2
result.append(a)
print(sum(result))
↓
Bon exemple
print(sum([i**2 for i in range(10)])
↓
Bon exemple
print(sum(i**2 for i in range(10)))
Recommended Posts