# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] slideshow={"slide_type": "slide"}
# # A `python` clan war

# + [markdown] slideshow={"slide_type": "fragment"}
# Short version: 
#
# * Python 2.x is **legacy**
# * Python 3.x is the **present** and **future** of the language

# + [markdown] slideshow={"slide_type": "subslide"}
# * Python was released in 1991
# * Python 2.0 was released in 2000
# * Python 3.0 was released in 2008. 
# * The final 2.x version 2.7 release came out in mid-2010
#     - with a statement
#     > extended support for this end-of-life release
#    

# + [markdown] slideshow={"slide_type": "subslide"}
# **The 2.x branch will see no new major releases.**
#
# 3.x is under active development and has already seen over SEVEN years of stable releases. 
# > Current release is `python 3.5`.
#
# This means that all recent standard library improvements, for example, are only available by default in Python 3.x.

# + [markdown] slideshow={"slide_type": "subslide"}
# ## How it all started
#
# <NAME> (the original creator of the Python language) decided to clean up Python 2.x **properly**.
#
# * less regard for backwards compatibility
# * most drastic improvement is the better Unicode support
#     * (all text strings being Unicode by default) 
#     * saner bytes/Unicode separation.
#
# Several other aspects of the core language have been adjusted to be easier for newcomers to learn.
#
# source: https://wiki.python.org/moin/Python2orPython3

# + [markdown] slideshow={"slide_type": "subslide"}
# ## The problems so far
#
# A list of well known excuses to not use Python 3
#
# * Not easy to switch to Python 3 if you're an hardcore Python 2 programmer
# * Not easy to port my Python 2 code into Python 3
# * Not easy to support Python 2 AND Python 3 when writing code
# * Not all famous libraries are available in Python 3

# + [markdown] slideshow={"slide_type": "subslide"}
# # NOT TRUE ANYMORE

# + [markdown] slideshow={"slide_type": "subslide"}
# * <strike>Not easy to switch to Python 3 if you're an hardcore Python 2 programmer</strike>
#     - **After 7 years you may find great resources like http://python3porting.com/differences.html**
# * Not easy to port my Python 2 code into Python 3
# * Not easy to support Python 2 AND Python 3 when writing code
# * Not all famous libraries are available in Python 3

# + [markdown] slideshow={"slide_type": "subslide"}
# * <strike>Not easy to switch to Python 3 if you're an hardcore Python 2 programmer</strike>
# * <strike>Not easy to port my Python 2 code into Python 3</strike>
#     - **Use `2to3` library, works for 90% of the code** https://docs.python.org/2/library/2to3.html
#     - there is also a `3to2` library, for the record
# * Not easy to support Python 2 AND Python 3 when writing code
# * Not all famous libraries are available in Python 3

# + [markdown] slideshow={"slide_type": "subslide"}
# * <strike>Not easy to switch to Python 3 if you're an hardcore Python 2 programmer</strike>
# * <strike>Not easy to port my Python 2 code into Python 3</strike>
# * <strike>Not easy to support Python 2 AND Python 3 when writing code</strike>
#     - **Use the `six` package (because `2*3 = 6`)** http://pythonhosted.org/six/index.html#module-six
# * Not all famous libraries are available in Python 3

# + [markdown] slideshow={"slide_type": "subslide"}
# * <strike>Not easy to switch to Python 3 if you're an hardcore Python 2 programmer</strike>
# * <strike>Not easy to port my Python 2 code into Python 3</strike>
# * <strike>Not easy to support Python 2 AND Python 3 when writing code</strike>
# * <strike>Not all famous libraries are available in Python 3</strike>
#     - **Anaconda (used by Jupyter on Docker) ported all their data stack to python3 **
#     - numpy, scipy, matplotlib, scikit-learn, and so on..

# + [markdown] slideshow={"slide_type": "slide"}
# ## The differences you need to know

# + [markdown] slideshow={"slide_type": "subslide"}
# * `print` function
# * str vs unicode
# * dictionaries
#
# <small> Other differences you would not notice until you go PRO </small>

# + [markdown] slideshow={"slide_type": "subslide"}
# How Jupyter Notebook may help to solve the issue:
#
# * different kernels
# * ipython magic

# + [markdown] slideshow={"slide_type": "slide"}
# ## [Main differences 01]: 
# ## Print function

# + [markdown] slideshow={"slide_type": "subslide"}
# The wrong way

# + language="python2"
# print "test"
# print "test",
# print "test", "two"

# + slideshow={"slide_type": "fragment"} language="python3"
# print "test"

# + [markdown] slideshow={"slide_type": "subslide"}
# A better way: always use print as a function, with parenthesis

# + language="python2"
# print("test")
# print("test", "two")

# + slideshow={"slide_type": "fragment"} language="python3"
# print("test")
# print("test", "two")

# + [markdown] slideshow={"slide_type": "subslide"}
# The best way is **one string** to the function

# + language="python2"
# print("test %s" % "two")
# var1 = "two"
# var2 = "three"
# print("test %s, %s" % (var1, var2))

# + language="python3"
# print("test %s" % "two")
# var1 = "two"
# var2 = "three"
# print("test %s, %s" % (var1, var2))

# + [markdown] slideshow={"slide_type": "subslide"}
# If writing Python real packages and/or projects, you should use `log`
# and avoid the `print` function as much as possible.

# + slideshow={"slide_type": "fragment"}
import logging
FORMAT = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
logging.basicConfig(format=FORMAT)
logger = logging.getLogger("notebook")
logger.setLevel(logging.DEBUG)
logger.debug("test")

# + slideshow={"slide_type": "subslide"}
var1 = "two"
var2 = "three"
logger.debug("test %s, %s" % (var1, var2))

# + [markdown] slideshow={"slide_type": "subslide"}
# Log levels: DEBUG < INFO < WARNING < CRITICAL < ERROR

# + slideshow={"slide_type": "fragment"}
logger.setLevel(logging.INFO)
logger.debug("test again")
# this time it will not show
logger.info("one last time")

# + [markdown] slideshow={"slide_type": "slide"}
# ## [Main differences 02]: 
# ## Strings and Unicode
#
# x.__unicode__().encode('utf-8')

# + slideshow={"slide_type": "subslide"} language="python2"
# mystring = 'test'
# myunicode = unicode(mystring, 'utf8')
#
# print mystring, type(mystring)
# print myunicode, type(myunicode)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Unicode literals
#
# * Adding from __future__ import unicode_literals at the top of your Python modules;
# * Removing the u prefix before unicode strings;
# * Adding a b prefix before bytestrings;
# * Performing these changes systematically guarantees backwards compatibility.
#
# source: [Django framework tips](https://docs.djangoproject.com/en/1.8/topics/python3/)

# + slideshow={"slide_type": "fragment"} language="python2"
# from __future__ import unicode_literals
# mystring = 'test'
# print type(mystring)

# + [markdown] slideshow={"slide_type": "subslide"}
# But...

# + slideshow={"slide_type": "fragment"} language="python3"
# mystring = 'test'
# from six import text_type
# print(type(mystring), type(text_type(mystring)))

# + [markdown] slideshow={"slide_type": "subslide"}
# In Python 3
#
# * Python 2’s unicode type was renamed str 
# * str() was renamed bytes
# * and basestring disappeared
#
# `six` provides tools to deal with these changes

# + slideshow={"slide_type": "fragment"} language="python2"
# import six
# myvalue = 'astring'
# isinstance(myvalue, six.string_types)       # replacement for basestring
# isinstance(myvalue, six.text_type)          # replacement for unicode
# isinstance(myvalue, bytes)                  # replacement for str

# + [markdown] slideshow={"slide_type": "subslide"}
# String classes and Unicode are the main reason why also Flask's author [got mad](http://lucumr.pocoo.org/2014/1/5/unicode-in-2-and-3/) on python3 core developers last year.
#
# His web framework has to deal with HTML raw text types, like bytes, encoding and so on.

# + [markdown] slideshow={"slide_type": "slide"}
# ## Quick tip: ask to *python* if you don't know

# + slideshow={"slide_type": "subslide"}
# ! howdoi get substring in python

# + [markdown] slideshow={"slide_type": "subslide"}
# A little trick for the command line:
#
# `howdoi` is a python package which queries google/stackoverflow and shows the best answer.

# + slideshow={"slide_type": "fragment"}
# ! howdoi

# + [markdown] slideshow={"slide_type": "slide"}
# ## [Main differences: 03] 
# ## Dictionaries methods

# + slideshow={"slide_type": "fragment"}
mydict = {
    "key":"value", 
    "anotherkey": "anothervalue"
}
mydict

# + slideshow={"slide_type": "subslide"}
# ! howdoi cycle py2 dictionaries

# + slideshow={"slide_type": "fragment"} language="python2"
# mydict = {
#     "key":"value", 
#     "anotherkey": "anothervalue"
# }
#
# for (key, value) in mydict.iteritems():
#     print("[%s]:\t%s" % (key, value))

# + slideshow={"slide_type": "subslide"}
# ! howdoi cycle py3 dictionaries

# + language="python3"
# mydict = {
#     "key":"value", 
#     "anotherkey": "anothervalue"
# }
#
# for (key, value) in mydict.items():
#     print("[%s]:\t%s" % (key, value))

# + [markdown] slideshow={"slide_type": "subslide"}
# In Python 2 dictionaries have the methods iterkeys(), itervalues() and iteritems() that return iterators instead of lists. 
#
# In Python 3 the standard keys(), values() and items() return dictionary views, which are iterators, so the iterator variants become pointless and are removed.

# + [markdown] slideshow={"slide_type": "subslide"}
# Saving both worlds

# + slideshow={"slide_type": "fragment"} language="python2"
# from six import iteritems
#
# mydict = {"key":"value", "anotherkey": "anothervalue"}
# for (key, value) in iteritems(mydict):
#     print("[%s]:\t%s" % (key, value))

# + language="python3"
# from six import iteritems
#
# mydict = {"key":"value", "anotherkey": "anothervalue"}
# for (key, value) in iteritems(mydict):
#     print("[%s]:\t%s" % (key, value))

# + [markdown] slideshow={"slide_type": "slide"}
# ## The most dramatic way to have a cross-python code

# + [markdown] slideshow={"slide_type": "fragment"}
# Another solution for having a code that works in both worlds
# is to make a strong assumption that even in Python2 you would act 
# like testing the new Python 3 features.
#
# Using the `__future__` import you can abandon in Python2 the original types and "mistakes".

# + slideshow={"slide_type": "subslide"} language="python2"
# from __future__ import print_function
# print "test"

# + slideshow={"slide_type": "subslide"} language="python2"
# print 6 / 4
# print(type("string"))

# + slideshow={"slide_type": "fragment"} language="python2"
# from __future__ import division
# from __future__ import print_function
# from __future__ import unicode_literals
#
# print(6 / 4)
# print(type("string"))

# + [markdown] slideshow={"slide_type": "slide"}
# # Not the end
#
# There are many projects emerging for working code on both python2 and python3
#
# e.g. http://python-future.org/

# + [markdown] slideshow={"slide_type": "slide"}
# # Choosing python 3

# + [markdown] slideshow={"slide_type": "fragment"}
# Be brave, and ahead of the future

# + [markdown] slideshow={"slide_type": "slide"}
# # A final note

# + slideshow={"slide_type": "subslide"}
from __future__ import braces

# + [markdown] slideshow={"slide_type": "slide"}
# # end of chapter

StarcoderdataJupyterScriptsDedupFiltered