import numpy as np
There are two popular options:
Important: whatever approach you choose, Be consistent
def get_min_value(lst):
out=min(lst)
return out
def get_max_value(lst):
out=max(lst)
return out
myList=np.array([0.3,4,1.5,5.7])
minValue=get_min_value(myList)
maxValue=get_max_value(myList)
print(minValue)
print(maxValue)
Temporary variables can be as short as a single character. Be consistent with names that have the same kind of role.
Important: Be consistent
#i for loop counters
for i in range(0,2):
#j for nested loop counters
for j in range(2,4):
print("Value i,j: %d,%d" %(i,j))
#out for returning variables
def create_zeros(n):
out=np.zeros(n)
return out
def create_ones(n):
out=np.ones(n)
return out
nZeros=create_zeros(2)
nOnes=create_ones(3)
print(nZeros)
print(nOnes)
def BusinessLogic(d):
# ....
return d*8*5*52 # WHAT ARE THOSE NUMBERS???
def BusinessLogic(work_days):
#.....
HOURS_PER_WORKDAY=8
WORKDAYS_PER_WEEK=5
WEEKS_PER_YEAR=52
return HOURS_PER_WORKDAY*WORKDAYS_PER_WEEK*WEEKS_PER_YEAR*work_days
# ...
def factorial(l):
if l==0:
return 1
else:
return l*factorial(l-1)
factValue=factorial(5)
print(factValue)
...even if your language does not enforce identation.
Compare:
#include <iostream>
int main(int argc, char** argv) { const char* name="world"; if (argc>2) { name=argv[1]; } std::cout << "Hello, " << name << "!" << std::endl; return 0; }
with:
#include <iostream>
int main(int argc, char** argv)
{
const char* name="world";
if (argc>2) {
name=argv[1];
}
std::cout << "Hello, "
<< name
<< "!"
<< std::endl;
return 0;
}
Although Python does enforce some identation, you are still responsible for readability:
# No: Further indentation required as indentation is not distinguishable.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
var_one=1
var_two=2
var_three=3
var_four=4
# No: Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Yes: More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
var_one=1
var_two=2
var_three=3
var_four=4
# Yes: Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Yes: Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
def do_stuff():
# ...
if (logical_condition1):
if (logical_condition2):
if (logical_condition3):
if (logical_condition4):
return True
else:
return False
else:
return False
else:
return False
else:
return False
def do_stuff():
# ...
if (logical_condition1 and logical_condition2 and logical_condition3 and logical_condition4):
return True
else:
return False
with open('/path/to/some/file/you/want/to/read') as file_1, \ open('/path/to/some/file/being/written', 'w') as file_2: file_2.write(file_1.read())
# No: operators sit far away from their operands
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
# Yes: easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
## Have you ever seen this?
def DoWork(arg):
# ... do some work ...
pass
# CAUTION: This function should never return 0!
return 0
x = x + 1 # No: Increment x
x = x + 1 # Yes: Compensate for border
Note: While it is true that sometimes a sub-problem can be more naturally expressed and/or easier and faster solved in some other language, it is not for the faint of heart! We may cover multi-language development in a future workshop.
import fibonacci
fib=fibonacci.ifib
print(fibonacci.fib(3))
print(fib(3))
def DoWork(arg):
# ... do some work ...
pass
assert out!=0, "This function should never return 0"
return out
class MyDB:
def __init__(self):
self._id2name_map = {}
self._name2id_map = {}
def add(self, id, name):
self._name2id_map[name] = id
self._id2name_map[id] = name
def by_name(self, name):
return self._name2id_map[name]
def by_name(self, name):
id = self._name2id_map[name]
assert self._id2name_map[id] == name
return id
from types import *
class MyDB:
...
def add(self, id, name):
assert type(id) is IntType, "id is not an integer: %r" % id
assert type(name) is StringType, "name is not a string: %r" % name
import pdb;
def add_to_life_universe_everything(x):
answer = 42
pdb.set_trace()
answer += x
return answer
add_to_life_universe_everything(12)
wordcount('foo bar foo ') {'foo': 2, 'bar': 1}
from wordcount import wordcount
class TestUnit(unittest.TestCase): def test_wordcount(self): self.assertDictEqual( {'foo' : 2, 'bar' : 1}, wordcount('foo bar foo '))
In Donald Knuth's paper "Structured Programming with go to
Statements", he wrote:
Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
def profileCommand(n):
out=1
for i in range(1, n+1):
out=out*i
return out
import cProfile
cProfile.run("result=profileCommand(2000)")
#print(result)
# For benchmark tests
from timeit import Timer
def test(x):
"Stupid test function"
L = [i for i in range(x)]
t = Timer("test(100)", "from __main__ import test")
print(t.timeit())
KISS stands for Keep It Simple and Stupid (figuratively speaking!)