-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathI Best Practices.py
226 lines (181 loc) · 7.77 KB
/
I Best Practices.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
"""**************************************************************************************************************************************************************
goal of this course is to transform you into a Python expert, and so the first chapter starts off with best practices when writing functions.
You'll cover docstrings and why they matter and how to know when you need to turn a chunk of code into a function. You will also learn the details of how Python passes
Docstrings
==========
- makes your code easier to use, read, maintain
@ anatomy of docstring
-----------------------
def func_name(arguments):
'''
Description of what it does
Description of argument(s) if any
Description of return value(s) if any
Description of errors raised if any
Optional extra notes or examples
'''
@ docstring Formats
-----------------------
- Google style (pupular) - NumpyDoc (popular) - reStructuredText - EpyText
----Google style === straight to the point eg. '''Stack the columns''' and just Arg:, Raises: , Returns: , Notes:
----NumpyDoc === more vertical with line tittles, takes more space
@ Review Documentation
-----------------------
>>>>>>>> func_name.__doc__ ====review documentation
>>>>>>>> .getdoc(dunc_name) (inspect module)
++
import inspect
print(inspect.getdoc(func_name))
**************************************************************************************************************************************************************"""
## Crafting a docstring
# Add a docstring to count_letter()
def count_letter(content, letter):
"""Count the number of times `letter` appears in `content`.
# Add a Google style arguments section
Args:
content (str): The string to search.
letter (str): The letter to search for.
# Add a returns section
Returns:
int
# Add a section detailing what errors might be raised
Raises:
ValuError: If `letter` is not a one-character string
"""
if (not isinstance(letter, str)) or len(letter) != 1:
raise ValueError('`letter` must be a single character string.')
return len([char for char in content if char == letter])
#`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
## Retrieving docstrings
# Get the "count_letter" docstring by using an attribute of the function
docstring = count_letter.__doc__
border = '#' * 28
print('{}\n{}\n{}'.format(border, docstring, border))
## Retrieving docstrings 2
import inspect
# Inspect the count_letter() function to get its docstring
docstring = inspect.getdoc(count_letter)
"""add borders"""
border = '#' * 28
print('{}\n{}\n{}'.format(border, docstring, border))
## Retrieving docstrings 3
import inspect
def build_tooltip(function):
"""Create a tooltip for any function that shows the
function's docstring.
Args:
function (callable): The function we want a tooltip for.
Returns:
str
"""
# Get the docstring for the "function" argument by using inspect
docstring = inspect.getdoc(function)
border = '#' * 28
return '{}\n{}\n{}'.format(border, docstring, border)
print(build_tooltip(count_letter))
print(build_tooltip(range))
print(build_tooltip(print))
"""!!!
. But when we want to print the docstring, removing those leading spaces with inspect.getdoc() will look much better."""
#`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
## Docstrings to the rescue!
"""---Examine each of these functions' docstrings in the IPython shell to determine which of them is actually numpy.histogram()."""
""" numpy.leyud(), numpy.uqka(), numpy.fywdkxa(), numpy.jinzyxq() """
import inspect
inspect.getdoc(numpy.fywdkxa)
'''Compute the histogram of a set of data.'''
# numpy.fywdkxa()
"""**************************************************************************************************************************************************************
DRY and "Do One Thing"
=====================
- Dry: Don't repeat yourself
- Do one thing: funtion for doing 1 thing
/ more flexible / easily undertood / simpler to test / simpler to debug / easier to change
/ Use functions to avoid repetition
- Refactor: improving code by changing it a little bit at a time
**************************************************************************************************************************************************************"""
## Extract a function
def standardize(column):
"""Standardize the values in a column.
Args:
column (pandas Series): The data to standardize.
Returns:
pandas Series: the values as z-scores
"""
# Finish the function so that it returns the z-scores
z_score = (column - column.mean()) / column.std()
return z_score
# Use the standardize() function to calculate the z-scores
df['y1_z'] = standardize(df.y1_gpa)
df['y2_z'] = standardize(df.y2_gpa)
df['y3_z'] = standardize(df.y3_gpa)
df['y4_z'] = standardize(df.y4_gpa)
#`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
## Split up a function
def mean(values):
"""Get the mean of a sorted list of values
Args:
values (iterable of float): A list of numbers
Returns:
float
"""
# Write the mean() function
mean = sum(values) / len(values)
return mean
## Split up a function 2
def median(values):
"""Get the median of a sorted list of values
Args:
values (iterable of float): A list of numbers
Returns:
float
"""
# Write the median() function
midpoint = int(len(values) / 2)
if len(values) % 2 == 0:
median = (values[midpoint - 1] + values[midpoint]) / 2
else:
median = values[midpoint]
return median
"""**************************************************************************************************************************************************************
Pass by assignment
===================
**************************************************************************************************************************************************************"""
## Mutable or immutable?
"""----What do you expect the values of d and s to be after the function is called?"""
def store_lower(_dict, _string):
"""Add a mapping between `_string` and a lowercased version of `_string` to `_dict`
Args:
_dict (dict): The dictionary to update.
_string (str): The string to add.
"""
orig_string = _string
_string = _string.lower()
_dict[orig_string] = _string
d = {}
s = 'Hello'
store_lower(d, s)
# d = {'Hello': 'hello'}, s = 'Hello'
"""!!!
Dictionaries are mutable objects in Python, so the function can directly change it"""
#`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
## Best practice for default arguments
# Use an immutable variable for the default argument
"""if df is none, create one"""
def better_add_column(values, df=None):
"""Add a column of `values` to a DataFrame `df`.
The column will be named "col_<n>" where "n" is
the numerical index of the column.
Args:
values (iterable): The values of the new column
df (DataFrame, optional): The DataFrame to update.
If no DataFrame is passed, one is created by default.
Returns:
DataFrame
"""
# Update the function to create a default DataFrame
"""DataFrame is created if the caller didn't pass one."""
if df is None:
df = pandas.DataFrame()
df['col_{}'.format(len(df.columns))] = values
return df