"""
Equivalences
You have a working code, and you want it to be more clean, more pretty, more readable.
This is what we call, refactoring.
Here is a list of transformation to help you in this task.
You can of course choose to apply the transformation or not.
A "→" means the code will probably be more readable (according to me).
A "↔" means the clarity will depend on the context (neither code is a priori more readable).
"""
##
# inverser if/else
##
if CONDITION:
A
else:
B
# ↔
if not(CONDITION):
B
else:
A
## example 1
if a == 5:
print("hello")
else:
waw = 2
# ↔ (invert if/else)
if not(a == 5):
waw = 2
else:
print("hello")
# ↔ (not == ↔ !=)
if a != 5:
waw = 2
else:
print("hello")
###
# else do nothing
###
if CONDITION:
A
else:
pass # do nothing
# →
if CONDITION:
A
## example 1
if a != 5:
print("hello")
else:
pass # do nothing
# → ("else do nothing" is useless)
if a != 5:
print("hello")
## example 2
if a == 5:
pass # do nothing
else:
print("hello")
# → (invert if/else)
if a != 5:
print("hello")
else:
pass # do nothing
# → ("else do nothing" is useless)
if a != 5:
print("hello")
###
# simplify not (De Morgan's laws)
###
# De Morgan on "and"
if not(A and B):
...
# ↔
if (not A) or (not B):
...
# De Morgan on "or"
if not(A or B):
...
# ↔
if (not A) and (not B):
...
## example 1
if not(a > 10 or a == 5):
print('hello')
# → (De Morgan)
if a <= 10 and a != 5:
print('hello')
## example 2
if a > 10 or a == 5:
pass
else:
print('hello')
# → (invert if/else)
if not(a > 10 or a == 5):
print('hello')
else:
pass
# → ("else do nothing" is useless)
if not(a > 10 or a == 5):
print('hello')
# → (De Morgan)
if a <= 10 and a != 5:
print('hello')
###
# if followed by if not
###
if a < b:
print("hello")
if a >= b:
print("tada")
# → (à condition que a et b ne soient pas modifiés dans le if !)
if a < b:
print("hello")
else:
print("tada")
###
# if variable
###
if CONDITION:
x = A
else:
x = B
# →
x = A if CONDITION else B
# →
x = (A if CONDITION else B)
# →
x = (A if CONDITION else
B)
## example
if a == 5:
c = 2
else:
c = 0
# → ("one-line if" also called "ternary operator" or "functional if")
c = (5 if a == 5 else 0)
# ↔ (parenthesis are useless)
c = 5 if a == 5 else 0
##
# if elif cascade on variable
##
if CONDITION:
x = A
elif CONDITION_2:
x = B
elif CONDITION_3:
x = C
else:
x = D
# →
x = (A if CONDITION else
B if CONDITION_2 else
C if CONDITION_3 else
D)
## example
if a == 5:
c = 8
elif a == 2:
c = 4
elif a < 0:
c = 1
else:
c = 0
# → (functional if)
c = (8 if a == 5 else
4 if a == 2 else
1 if a < 0 else
0)
##
# renaming
##
#
# You can rename a variable to give it a name more explicit :
e = v * t
i = e / 2.56
# →
distance = velocity * time
distance_inch = distance / 2.56
# Generally variable names of few letters are <strong>too short</strong>
# (except in mathematical expressions or well known variable names like the <code>"i"</code> in a loop)
# and variable names with more than three real words are <strong>too long</strong>
# (a comment next to the variable creation will be probably better).
##
# inline variable
##
x = ...
operation(x)
# → (only possible if x is used only once)
operation(...)
## example
x = size + 1 # x depends on the size
y = size - 1 # y depends on the size
the_coefficent = x + 2 * y # let's compute the coefficent using the linear formula
print(the_coefficent) # let's print it
# ↔ (inline variable "the_coefficent")
x = size + 1 # x depends on the size
y = size - 1 # y depends on the size
print(x + 2 * y) # let's print the result of the linear formula
# ↔ (inline variables "x" and "y")
print((size + 1) + 2 * (size - 1)) # let's print the result of the linear formula depending on the size
##
# boolean return
##
def f(...):
...
if CONDITION:
return True
else:
return False
# →
def f(...):
...
return CONDITION
## avec une variable
if CONDITION:
res = True
else:
res = False
# →
res = CONDITION
## example 1
def is_even(x):
if x % 2 == 0: # if the rest of division by 2 is 0
return True # Vrai, le nombre est pair
else: # sinon
return False # Faux, le nombre n'est pas pair
# → (boolean return)
def is_even(x):
return x % 2 == 0 # x is even iff the rest of division by 2 is 0
# :
if is_even(4):
...
## example 1'
if x % 2 == 0: # if the rest of division by 2 is 0
res = True # le résultat est Vrai, le nombre est pair
else: # sinon
res = False # le résultat est Faux, le nombre n'est pas pair
# → (boolean return)
res = (x % 2 == 0) # the result is true iff the rest of division by 2 is 0
# → (renaming)
is_even = (x % 2 == 0) # on nomme la variable de manière sémantique
# ↔ (parenthesis)
is_even = x % 2 == 0 # parenthèses non nécessaires
## example 2
def vowel(x):
if x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u':
return True
else:
return False
# → (boolean return)
def vowel(x):
return x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u' # x is a vowel iff x is 'a', 'e', 'i', 'o', 'u'
# :
if vowel('a'): # if 'a' is a vowel
...
##
# == True
##
# given
def is_even(x):
if x % 2 == 0: # if the rest of division by 2 is 0
return True
else:
return False
# :
if is_even(4) == True: # si the is_even function returns True
...
# →
if is_even(4): # if 4 is even
...
##
# or
##
if CONDITION:
A
elif CONDITION_2:
A # same A
# →
if CONDITION or CONDITION_2:
A
## example
if a == 5:
x = 2
elif a > 10:
x = 2
# → (or)
if a == 5 or a > 10:
x = 2
##
# or else
##
if CONDITION:
A
elif CONDITION_2:
A # same A
else:
B
# →
if CONDITION or CONDITION_2:
A
else:
B
## example
if a == 5:
x = 2
elif a > 10:
x = 2
else:
print('error')
# → (or)
if a == 5 or a > 10:
x = 2
else:
print('error')
##
# or return
##
def f(...):
...
if CONDITION:
return True
if CONDITION_2:
return True
return False
# →
def f(...):
...
return CONDITION or CONDITION_2
# ↔
def f(...):
...
return (CONDITION
or CONDITION_2)
## example
def interesting(x):
if x > 10: # if x > 10
return True # it's interesting
if x == 5: # if x == 5
return True # it's interesting
return False # otherwise, it's not interesting
# → (or return)
def interesting(x):
return x > 10 or x == 5 # x is interesting if it's > 10 or 5
##
# and
##
if CONDITION:
if CONDITION_2:
A
# →
if CONDITION and CONDITION_2:
A
## example
if a == 5:
if a > 10:
print('waw')
# → (and)
if a == 5 and a > 10:
print('waw')
##
# and else
##
if CONDITION:
if CONDITION_2:
A
else:
B
else:
B # same b
# →
if CONDITION and CONDITION_2:
A
else:
B
## example
if a == 5:
if b > 10:
waw = 2
else:
print('error')
else:
print('error')
# → (and)
if a == 5 and b > 10:
waw = 2
else:
print('error')
##
# if return
##
def f(...):
...
if CONDITION:
return X
...
# ↔
def f(...):
...
if CONDITION:
return X
else:
...
## example
def f(x):
if x < 0:
return -1
else:
y = x + 2
z = y ** 2
return z
# → (if return)
def f(x):
if x < 0:
return -1
y = x + 2
z = y ** 2
return z
# I generally do that when the <code>"if"</code> is really short like a simple <code>"return"</code>.
# Souvent, ce sont des cas particuliers ou des cas de base, le code du bas est plus intéressant.
##
# for if return True (∃)
## for-if-return-True, any, exists, ∃
# Here is how we code a "∃"
def f(...):
...
for x in L:
if condition: # this "if" DOESN'T have a "else"
return True
return False
# → (en python, il y a "all")
def f(...):
...
return any(condition for x in L)
# ↔
def f(...):
...
return any(condition
for x in L)
# Note: in python there is also the [for...else](https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops#9980752) but not so much people use it
## example
def contains_a_negative(L):
for x in L: # for each element in the list
if x < 0: # if it's < 0
return True # the list contains_a_negative
return False # in the end, it means it doesn't contain one
# → (any)
def contains_a_negative(L):
return any(x < 0 for x in L)
# We'll read it as <em>A list L contains_a_negative if...</em>
# <ul>
# <li> there is a x < 0
# <li> there exists any x such that x < 0
# <li> ∃ x ∈ L: x < 0
# </ul>
##
# for if return False (∀)
## for-if-return-False, all, forall, ∀
# Here is how we code a "∀"
def f(...):
...
for x in L:
if condition: # this "if" DOESN'T have a "else"
return False
return True
# → (en python, il y a "all")
def f(...):
return all(not condition for x in L)
# ↔
def f(...):
return all(not condition
for x in L)
# Note: in python there is also the [for...else](https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops#9980752) but not so much people use it
## example
def totally_positive(L):
for x in L: # for each element in the list
if x < 0: # if it's < 0
return False # the list is not totally_positive
return True # in the end, the list is totally_positive
# → (all)
def totally_positive(L):
return all(x >= 0 for x in L)
# We'll read it as <em>A list L is totalement_positive if</em>...
# <ul>
# <li> A list is totally positive if all its elements x are >= 0
# <li> for all its elements x one have x >= 0
# <li> any element x ∈ L satisfies x >= 0
# <li> ∀ x ∈ L : x >= 0
# </ul>
##
# not ∀/∃ (De Morgan's laws)
## not-any, not-all
# De Morgan on "∀"
not all(condition for x in L)
# →
any(not condition for x in L)
# De Morgan on "∃"
not any(condition for x in L)
# →
all(not condition for x in L)
## example
if not all(x >= 0 for x in L): # si on n'a pas tous les nombres >= 0
...
# → (if non empty)
if any(x < 0 for x in L): # c'est qu'il existe un nombre < 0
...
# <strong>Attention</strong>: cette transformation ne marche pas si L est vide !
#
##
# for if return else return
##
# Here is how one code a linear search
def f(...):
for x in L:
if condition:
return a
return b
# → (in python, one can use "next")
def f(...):
return next((a for x in L if condition), b)
# ↔
def f(...):
return next((a for x in L if condition),
b)
# Note: in python there is also the [for...else](https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops#9980752) but not so much people use it
## example
#
# <em>Le super_nombre d'une liste est le <strong>premier</strong> x dans la liste tel que x > 10</em> :
def super_number(L):
for x in L: # for each element in the list
if x > 10: # if it's > 10
return x # it's the super_number of that list
return 0 # il n'y a pas de super nombre, on renvoie 0
# →
def super_number(L):
return next((x for x in L if x > 10), 0)
##
# for append
##
L = []
for x in iterable:
L.append(e)
# →
L = [e for x in iterable]
##
# for append f(x)
## +, map
L = []
for x in iterable:
L.append(f(x))
# →
L = list(map(f, iterable))
# ↔
L = [f(x) for x in iterable]
##
# for if append
##
L = []
for x in iterable:
if condition:
L.append(e)
# →
L = [e for x in iterable if condition]
##
# for if f(x) append x
## +, filter
L = []
for x in iterable:
if f(x):
L.append(x)
# →
L = list(filter(f, iterable))
# ↔
L = [x for x in iterable if f(x)]
##
# iterate a generator (python)
##
for x in list(generator):
...
# →
for x in generator:
...
## example 1
for x in list(map(f, L)): # map, filter, zip...
...
# →
for x in map(f, L):
...
## example 2
# with
def operation(x):
return (x + 1) * 2 - x
# :
for x in list(map(operation, [1,2,3])):
print(x)
# →
for x in map(operation, [1,2,3]):
print(x)
##
# sum
##
## example
s = 0
for x in L:
s += a
# → (sum)
s = sum(a for x in L)
# technically, "sum" is a particular case of "reduce" but "reduce" is a bit useless in python
##
# join
##
## example
s = ''
for x in L:
s += a
# → (join)
s = ''.join(a for x in L)
# technically, "join" is a particular case of "reduce" but "reduce" is a bit useless in python
##
# in tuple (python)
##
## example
if x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u':
...
# → (in)
if x in ('a', 'e', 'i', 'o', 'u'):
...
# it's a particular case of linear search in a list