Skip to content

Commit ef7d163

Browse files
committed
Resolve merge conflicts.
2 parents 1bd8349 + 9780b29 commit ef7d163

9 files changed

Lines changed: 57 additions & 60 deletions

classes.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ going!
99
1. Instance & Class variables
1010
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1111

12-
Most beginners and even some advance Python programmers do not
12+
Most beginners and even some advanced Python programmers do not
1313
understand the distinction between instance and class variables. Their
1414
lack of understanding forces them to use these different types of
1515
variables incorrectly. Let's understand them.
@@ -53,7 +53,7 @@ Let's take a look at an example:
5353
b.pi
5454
# Output: 50
5555
56-
There are not much issues while using mutable class variables. This is
56+
There are not many issues while using mutable class variables. This is
5757
the major reason due to which beginners do not try to learn more about
5858
this subject because everything works! If you also believe that instance
5959
and class variables can not cause any problem if used incorrectly then
@@ -90,7 +90,7 @@ make your code safe against this kind of surprise attacks then make sure
9090
that you do not use mutable class variables. You may use them only if
9191
you know what you are doing.
9292

93-
2.New style classes:
93+
2. New style classes
9494
^^^^^^^^^^^^^^^^^^^^
9595

9696
New style classes were introduced in Python 2.1 but a lot of people do
@@ -130,16 +130,17 @@ classes.
130130
whether you subclass from ``object`` or not. However it is recommended
131131
that you still subclass from ``object``.
132132

133-
3.Magic Methods:
133+
3. Magic Methods
134134
^^^^^^^^^^^^^^^^
135135

136136
Python's classes are famous for their magic methods, commonly called
137-
**dunder** methods. I am going to discuss a few of them.
137+
**dunder** (double underscore) methods. I am going to discuss a few of
138+
them.
138139

139140
- ``__init__``
140141

141142
It is a class initializer. Whenever an instance of a class is created
142-
it's ``__init__`` method. For instance:
143+
its ``__init__`` method is called. For example:
143144

144145
.. code:: python
145146

collections.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ major one is that unlike lists, **you can not change a value in a
205205
tuple**. In order to access the value in a tuple you use integer indexes
206206
like:
207207

208-
::
208+
.. code:: python
209209
210210
man = ('Ali', 30)
211211
print(man[0])
@@ -217,7 +217,7 @@ integer indexes for accessing members of a tuple. You can think of
217217
namedtuples like dictionaries but unlike dictionaries they are
218218
immutable.
219219

220-
::
220+
.. code:: python
221221
222222
from collections import namedtuple
223223
@@ -244,7 +244,7 @@ memory than regular tuples. This makes them faster than dictionaries.
244244
However, do remember that as with tuples, **attributes in namedtuples
245245
are immutable**. It means that this would not work:
246246

247-
::
247+
.. code:: python
248248
249249
from collections import namedtuple
250250
@@ -260,7 +260,7 @@ You should use named tuples to make your code self-documenting. **They
260260
are backwards compatible with normal tuples**. It means that you can use
261261
integer indexes with namedtuples as well:
262262

263-
::
263+
.. code:: python
264264
265265
from collections import namedtuple
266266
@@ -272,7 +272,7 @@ integer indexes with namedtuples as well:
272272
Last but not the least, you can convert a namedtuple to a dictionary.
273273
Like this:
274274

275-
::
275+
.. code:: python
276276
277277
from collections import namedtuple
278278

context_managers.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ the ``with`` statement. Suppose you have two related operations which
77
you’d like to execute as a pair, with a block of code in between.
88
Context managers allow you to do specifically that. For example:
99

10-
::
10+
.. code:: python
1111
1212
with open('some_file', 'w') as opened_file:
1313
opened_file.write('Hola!')
@@ -16,7 +16,7 @@ The above code opens the file, writes some data to it and then closes
1616
it. If an error occurs while writing the data to the file, it tries to
1717
close it. The above code is equivalent to:
1818

19-
::
19+
.. code:: python
2020
2121
file = open('some_file', 'w')
2222
try:
@@ -42,7 +42,7 @@ At the very least a context manager has an ``__enter__`` and
4242
``__exit__`` methods defined. Let's make our own file opening Context
4343
Manager and learn the basics.
4444

45-
::
45+
.. code:: python
4646
4747
class File(object):
4848
def __init__(self, file_name, method):
@@ -55,7 +55,7 @@ Manager and learn the basics.
5555
Just by defining ``__enter__`` and ``__exit__`` methods we can use it in
5656
a ``with`` statement. Let's try:
5757

58-
::
58+
.. code:: python
5959
6060
with File('demo.txt', 'w') as opened_file:
6161
opened_file.write('Hola!')
@@ -87,7 +87,7 @@ What if our file object raises an exception? We might be trying to
8787
access a method on the file object which it does not supports. For
8888
instance:
8989

90-
::
90+
.. code:: python
9191
9292
with File('demo.txt', 'w') as opened_file:
9393
opened_file.undefined_function('Hola!')
@@ -107,15 +107,15 @@ In our case the ``__exit__`` method returns ``None`` (when no return
107107
statement is encountered then the method returns ``None``). Therefore,
108108
``with`` statement raises the exception.
109109

110-
::
110+
.. code:: python
111111
112112
Traceback (most recent call last):
113113
File "<stdin>", line 2, in <module>
114114
AttributeError: 'file' object has no attribute 'undefined_function'
115115
116116
Let's try handling the exception in the ``__exit__`` method:
117117

118-
::
118+
.. code:: python
119119
120120
class File(object):
121121
def __init__(self, file_name, method):
@@ -146,7 +146,7 @@ Python has a contextlib module for this very purpose. Instead of a
146146
class, we can implement a Context Manager using a generator function.
147147
Let's see a basic, useless example:
148148

149-
::
149+
.. code:: python
150150
151151
from contextlib import contextmanager
152152
@@ -177,7 +177,7 @@ Let's dissect this method a little.
177177
So now that we know all this, we can use the newly generated Context
178178
Manager like this:
179179

180-
::
180+
.. code:: python
181181
182182
with open_file('some_file') as f:
183183
f.write('hola!')

decorators.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ decorators can make your code concise.
99

1010
Firstly let's discuss how to write your own decorator.
1111

12-
It is perhaps one of the most difficult concept to grasp. We will take
12+
It is perhaps one of the most difficult concepts to grasp. We will take
1313
it one step at a time so that you can fully understand it.
1414

1515
Everything in python is an object:
1616
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1717

1818
First of all let's understand functions in python:
1919

20-
::
20+
.. code:: python
2121
2222
def hi(name="yasoob"):
2323
return "hi " + name
@@ -48,7 +48,7 @@ So those are the basics when it comes to functions. Lets take your
4848
knowledge one step further. In Python we can define functions inside
4949
other functions:
5050

51-
::
51+
.. code:: python
5252
5353
def hi(name="yasoob"):
5454
print "now you are inside the hi() function"
@@ -86,7 +86,7 @@ Returning functions from within functions:
8686
It is not necessary to execute a function within another function, we
8787
can return it as an output as well:
8888

89-
::
89+
.. code:: python
9090
9191
def hi(name="yasoob"):
9292
def greet():
@@ -125,7 +125,7 @@ function will be returned. We can also do print ``hi()()`` which outputs
125125
Giving a function as an argument to another function:
126126
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127127

128-
::
128+
.. code:: python
129129
130130
def hi():
131131
return "hi yasoob!"
@@ -147,7 +147,7 @@ Writing your first decorator:
147147
In the last example we actually made a decorator! Lets modify the
148148
previous decorator and make a little bit more usable program:
149149

150-
::
150+
.. code:: python
151151
152152
def a_new_decorator(a_func):
153153
@@ -181,7 +181,7 @@ wondering that we did not use the @ anywhere in our code? That is just a
181181
short way of making up a decorated function. Here is how we could have
182182
run the previous code sample using @.
183183

184-
::
184+
.. code:: python
185185
186186
@a_new_decorator
187187
def a_function_requiring_decoration():
@@ -200,19 +200,19 @@ run the previous code sample using @.
200200
I hope you now have a basic understanding of how decorators work in
201201
Python. Now there is one problem with our code. If we run:
202202

203-
::
203+
.. code:: python
204204
205205
print(a_function_requiring_decoration.__name__)
206206
# Output: wrapTheFunction
207207
208-
That's not what we expected! It's name is
208+
That's not what we expected! Its name is
209209
"a\_function\_requiring\_decoration". Well our function was replaced by
210210
wrapTheFunction. It overrode the name and docstring of our function.
211211
Luckily Python provides us a simple function to solve this problem and
212212
that is ``functools.wraps``. Let's modify our previous example to use
213213
``functools.wraps``:
214214

215-
::
215+
.. code:: python
216216
217217
from functools import wraps
218218
@@ -291,7 +291,7 @@ authentication:
291291
def decorated(*args, **kwargs):
292292
auth = request.authorization
293293
if not auth or not check_auth(auth.username, auth.password):
294-
return authenticate()
294+
authenticate()
295295
return f(*args, **kwargs)
296296
return decorated
297297

for_-_else.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ one.
99
Let's first start of by what we know. We know that we can use for loops
1010
like this:
1111

12-
::
12+
.. code:: python
1313
1414
fruits = ['apple', 'banana', 'mango']
1515
for fruit in fruits:
@@ -67,7 +67,7 @@ It outputs the prime numbers between 2 to 10. Now for the fun part. We
6767
can add an additional ``else`` block which catches the numbers which are
6868
not prime and tells us so:
6969

70-
::
70+
.. code:: python
7171
7272
for n in range(2, 10):
7373
for x in range(2, n):

function_caching.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,4 @@ is a generic cache:
6969
7070
`Here <https://www.caktusgroup.com/blog/2015/06/08/testing-client-side-applications-django-post-mortem/>`__
7171
is a fine article by Caktus Group in which they caught a bug in Django
72-
which occurred due to lru\_cache. It's an interesting read. Do check it
73-
out.
72+
which occurred due to ``lru_cache``. It's an interesting read. Do check it out.

global_&_return.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Global & Return
22
---------------
33

44
You might have encountered some functions written in python which have a
5-
return keyword in the end of the function. Do you know what it does? It
5+
``return`` keyword in the end of the function. Do you know what it does? It
66
is similar to return in other languages. Lets examine this little
77
function:
88

lambdas.rst

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ they are used in the wild:
3232
a.sort(key=lambda x: x[1])
3333
3434
print(a)
35-
# Output: [(13, -3), (4, 1), (1, 2), (9, 10)]
35+
# Output: [(13, -3), (4, 1), (1, 2), (9, 10)]
3636
3737
**Parallel sorting of lists**
3838

@@ -41,5 +41,3 @@ they are used in the wild:
4141
data = zip(list1, list2)
4242
data.sort()
4343
list1, list2 = map(lambda t: list(t), zip(*data))
44-
45-
Note: We will learn about map in a later chapter so don't worry!

targeting_python_2_3.rst

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ Targeting Python 2+3
22
--------------------
33

44
In a lot of cases you might want to develop programs which can be run in
5-
both, Python 2+ and 3+.
5+
both Python 2+ and 3+.
66

7-
Just imagine that you have a very popular python module which is use by
8-
hundreds of people but not all of them have python 2 or 3. In that case
7+
Just imagine that you have a very popular Python module which is use by
8+
hundreds of people but not all of them have Python 2 or 3. In that case
99
you have two choices. The first one is to distribute 2 modules, one for
10-
python 2 and the other for python 3. The other choice is to modify your
11-
current code and make is compatible with both python 2 and 3.
10+
Python 2 and the other for Python 3. The other choice is to modify your
11+
current code and make is compatible with both Python 2 and 3.
1212

1313
In this section I am going to highlight some of the tricks which you can
1414
employ to make a script compatible with both of them.
@@ -19,7 +19,7 @@ The first and most important method is to use ``__future__`` imports. It
1919
allows you to import Python 3 functionality in Python 2. Here is an
2020
example:
2121

22-
- Context manager were new in Python 3. For using them in Python 2.5+
22+
- Context managers were new in Python 2.6+. For using them in Python 2.5
2323
you can use:
2424

2525
.. code:: python
@@ -57,28 +57,28 @@ Do you know that you can do something like this as well?
5757
5858
import foo as foo
5959
60-
I know it’s function is the same as above listed code but it is vital
61-
for making your script compatible with python 2 and 3. Now examine the
60+
I know its function is the same as the above listed code but it is vital
61+
for making your script compatible with Python 2 and 3. Now examine the
6262
code below :
6363

6464
.. code:: python
6565
6666
try:
67-
import urllib.request as urllib_request # for python 3
67+
import urllib.request as urllib_request # for Python 3
6868
except ImportError:
69-
import urllib2 as urllib_request # for python 2
69+
import urllib2 as urllib_request # for Python 2
7070
7171
So let me explain the above code a little. We are wrapping our importing
72-
code in a try except clause. We are doing it because in python2 there is
73-
no urllib.request module and will result in an ImportError. The
74-
functionality of urllib.request is provided by urllib2 module in
75-
python2. So now when in Python2 we try to import ``urllib.request`` and
76-
get an ``ImportError`` we tell Python to import urllib2 instead.
72+
code in a try except clause. We are doing it because in Python 2 there is
73+
no ``urllib.request`` module and will result in an ImportError. The
74+
functionality of ``urllib.request`` is provided by ``urllib2`` module in
75+
Python 2. So now when in Python 2 we try to import ``urllib.request`` and
76+
get an ``ImportError`` we tell Python to import ``urllib2`` instead.
7777

7878
The final thing you need to know about is the ``as`` keyword. It is
7979
mapping the imported module to ``urllib_request``. So that now all of
80-
the Classes and methods of urllib2 are available to us by
81-
urllib\_request.
80+
the Classes and methods of ``urllib2`` are available to us by
81+
``urllib_request``.
8282

8383
**Obsolete Python 2 builtins**
8484

@@ -111,7 +111,6 @@ functionality in Python 2. For instance we have:
111111
- singledispatch ``pip install singledispatch``
112112
- pathlib ``pip install pathlib``
113113

114-
115-
I am sure there are a lot of other methods and tricks which can be used
116-
to make you code compatible with both of these Python series. This was
117-
just to give you some ideas.
114+
For further reading, the Python documentation has a `comprehensive guide
115+
<https://docs.python.org/3/howto/pyporting.html>`_ of steps you need to
116+
take to make your code compatible with both Python 2 and 3.

0 commit comments

Comments
 (0)