A Quick guide to Python - Notebook | Beginners

Tamoghna Saha
Nov 6, 2018 · 12 min read
Image for post
Image for post

I have been working with Python for the past 2 years. There are lots of tutorials available online that covers Python, but sometimes it doesn’t cover the most crucial part which needs an answer -
Why do we need to use Python?
Is it worth learning it?”.
Since you have clicked this article, and reading till this point, I can assume that you are interested in Python or maybe you do know something about it but you need a quick recap. I am here to guide you not only with the syntax but also to tell some concepts, tips and tricks associated with it.

Table of Content:

  • Numerical and Boolean Operations
  • Variable and Object
  • Data Type and Type Conversion
  • Importing Python Modules and standard libraries
  • Python Built-in Functions and keywords
  • String operations and formatting
  • Useful Pythonic Functions
  • User Input Function
  • User-Defined Function
  • Scope of a Variable
  • Additional Read

What is Python?

It is a general-purpose, high-level, interpreted, dynamic scripting language.

  • General-Purpose -> designed to be used for writing software in the widest variety of application domains
  • High-level -> designed to be more or less independent of a particular type of computer, human-readable friendly
  • Interpreted -> designed to execute instructions of a program directly, without previously compiling a program into machine-language instructions
  • Scripting -> languages which are interpreted rather than compiled

But, what is the difference between an interpreter and a compiler?

Currently, there are two versions of Python

Image for post
Image for post

Why do we need Python?

Image for post
Image for post
  • Simple syntax, readable, reusable and maintainable code
  • Multiple Programming Paradigms such as Object-oriented, structured, functional Paradigms and feature of automatic memory management
  • Compatible with Major Platforms and Systems, many open-source framework available which boosts developer’s productivity
  • Robust Standard Library and supporting wide range of external libraries
  • Easier to perform coding and testing simultaneously by adopting test driven development (TDD) approach

That’s okay. But where do I use it?

Image for post
Image for post

Who uses Python anyway?

Image for post
Image for post

Cool. I guess we are good to go!

Image for post
Image for post
# This is how you comment a code in Python!# Let’s start with the famous code.>>> print(‘Hello World’)Hello World# a collection of 20 software principles that influences the design of Python Programming Language, of which 19 were written down>>> import thisThe Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Numerical and Boolean Operations

## some basic mathematical operations , I am not showing. You do it. But see this.>>> print(25/4)
>>> print(25//4)
>>> print(25%4)
>>> x = 3
>>> x *= 3 # in-place operator
>>> print(x)
>>> y = “python”
>>> y += “3”
>>> print(y)

In Python 3, / is called floating point division and // is floor division. But In Python 2.7, it will return the base integer (6 in this case) in both the divisions.

Let’s look at some Boolean operations.

>>> print(“Easy ones!\n — — — — -”)
>>> print(2 == 3)
>>> print(6 != 7)
>>> print(9 is not “nine”)
>>> print(5 > 3)
>>> print(“ — — — — -”)
>>> print(“Tricky ones!\n — — — — -”)
>>> print(6 < 6.0)
>>> print((3 * 0.1) == 0.3)
>>> print((3 * 0.1) == (3/10))
Easy ones!
Tricky ones!

Floating point numbers are represented in computer hardware in base 2. Floating point numbers are usually represented in base 10. But most decimal fractions cannot be represented exactly as binary fractions. As a result, the decimal floating-point numbers you enter are only approximated to the binary floating-point numbers actually stored in the machine.

No matter how many base 2 digits you are willing to use, the decimal value 0.1 cannot be represented exactly as a base 2 fraction.

Many users are not aware of the approximation because of the way values are displayed. If Python were to print the true decimal value of the binary approximation stored for 0.1, it would have to display

>>> 0.1

But this is more digits than most people find useful, so Python keeps the number of digits manageable by displaying a rounded value instead

>>> 0.1

So, even though printed result looks like the exact value of 1/10, the actual stored value is the nearest representable binary fraction.

Note that this is in the very nature of binary floating-point: this is NOT a bug in Python. You’ll see the same kind of thing in all languages that support your hardware’s floating-point arithmetic. The errors in Python float operations are inherited from the floating-point hardware.

Variables and Objects

Few things about variables:

  • Variables do not have a defined type at compile time.
  • Variables can reference any type of object!
  • Variable type can change in run-time.

Type checking is performed at run-time, and hence dynamic languages are slower than static languages.

Everything in Python is an Object! object is the base type for every Python Object. Objects can be:

  • Mutable: value can be changed. [list, set, dictionaries]
  • Immutable: value is unchangeable. [number, string, frozenset, tuple]

Object mutability is defined by its type. They Are Never Explicitly Destroyed! Allocation and deletion is done by the interpreter.

The most commonly used methods of constructing a multi-word variable name are as follows:

  • Camel Case: Second and subsequent words are capitalized, to make word boundaries easier to see.Example: numberOfCollegeGraduates
  • Pascal Case: Identical to Camel Case, except the first word is also capitalized.Example: NumberOfCollegeGraduates
  • Snake Case: Words are separated by underscores.Example: number_of_college_graduates
# the correct ways to declare variables 
>>> my_variable = “is my variable, None of your variable” # even this is right
# definitely the wrong way to declare variables
>>> 1234_get_on_the_dance_floor = "really?" # this is wrong. see what error you will get

Data Type and Type Conversion

# data types
>>> print(type(“hello”))
>>> print(type(True))
>>> print(type(999.666))
>>> print(type((-1+0j)))
<class 'str'>
<class 'bool'>
<class 'float'>
<class 'complex'>
# type conversion>>> print(float(6))
>>> print("We are using Python " + str(3))
>>> print(int(“3”) + int(“6”))
We are using Python 3

Importing Python Modules and standard libraries

There are several ways to import standard and open-source external libraries to your programming environment:

# 1. By directly import
>>> import math
>>> print(math.sin(45))
>>> print("="*50)
# 2. By importing everything
>>> from math import *
# 3. Using alias
>>> import math as m
# 4. By specifically importing its functions
>>> from math import sin, log
>>> print(sin(45))
>>> print(log(5))

Some of the default modules in Python

  • sys -> System-specific parameters and functions.
  • io -> Core tools for working with streams.
  • os -> Miscellaneous operating system interfaces.
  • threading -> Higher-level threading interface.
  • multiprocess -> Process — based “threading“ interface.
  • socket -> Low — level networking interface.
  • asyncio -> Asynchronous I/O, event loop, co-routines and tasks.
  • cmd -> Support for line — oriented command interpreters.
  • datetime -> Basic date and time types.
  • time -> Time access and conversions.
  • heapq -> Heap queue algorithm.
  • queue -> A synchronized queue class.
  • pathlib -> Object — oriented filesystem paths
  • math -> Mathematical functions
  • sqlite3 -> DB — API interface for SQLite3 Databases.

Python Built-in Functions and keywords

Built-in functions are core functions, provided by the Python Interpreter. These functions are implemented in C and hence are capable of using and manipulating Python objects at memory level, with increased performance.

Keywords are basically reserved words. It can’t be used as variable’s names.

# just wrote these code to display the list properly in notebook# built-in functions
>>> builtin_functions_list = dir(__builtins__)
>>> builtin_functions_data = np.array(builtin_functions_list)
>>> shape = ((len(builtin_functions_list)//4),4)
>>> print(tabulate(builtin_functions_data.reshape(shape), tablefmt='orgtbl'))
| ArithmeticError | AssertionError | AttributeError | BaseException | BlockingIOError | BrokenPipeError | BufferError | BytesWarning
| ChildProcessError | ConnectionAbortedError | ConnectionError | ConnectionRefusedError
| ConnectionResetError | DeprecationWarning | EOFError | Ellipsis | EnvironmentError | Exception | False | FileExistsError
| FileNotFoundError | FloatingPointError | FutureWarning | GeneratorExit | IOError | ImportError | ImportWarning | IndentationError | IndexError | InterruptedError | IsADirectoryError | KeyError
| KeyboardInterrupt | LookupError | MemoryError | ModuleNotFoundError | NameError | None | NotADirectoryError | NotImplemented
| NotImplementedError | OSError | OverflowError | PendingDeprecationWarning
| PermissionError | ProcessLookupError | RecursionError | ReferenceError | ResourceWarning | RuntimeError | RuntimeWarning | StopAsyncIteration | StopIteration | SyntaxError | SyntaxWarning | SystemError
| SystemExit | TabError | TimeoutError | True | TypeError |UnboundLocalError | UnicodeDecodeError | UnicodeEncodeError | UnicodeError | UnicodeTranslateError| UnicodeWarning | UserWarning
| ValueError | Warning |ZeroDivisionError | __IPYTHON__ | __build_class__ | __debug__ | __doc__ | __import__ | __loader__ | __name__ | __package__ | __spec__
| abs | all | any | ascii | bin | bool | bytearray | bytes | callable | chr | classmethod | compile
| complex | copyright | credits | delattr | dict | dir | display | divmod | enumerate | eval | exec | filter
| float | format | frozenset | get_ipython | getattr | globals | hasattr | hash | help | hex | id | input
| int | isinstance | issubclass | iter | len | license | list | locals | map | max | memoryview | min
| next | object | oct | open | ord | pow | print | property | range | repr | reversed | round
| set | setattr | slice | sorted | staticmethod | str | sum | super | tuple | type | vars | zip
### keywords
>>> keywords_list = keyword.kwlist
>>> keywords_data = np.array(keywords_list)
>>> shape = ((len(keywords_list)//3),3)
>>> print(tabulate(keywords_data.reshape(shape), tablefmt='orgtbl'))
| False | None | True |
| and | as | assert |
| break | class | continue |
| def | del | elif |
| else | except | finally |
| for | from | global |
| if | import | in |
| is | lambda | nonlocal |
| not | or | pass |
| raise | return | try |
| while | with | yield |

String operations and formatting

## Concatenation>>> str_var_1 = "concatenation"
>>> print("This is " + str_var_1 + " of string")
>>> print(3*"3")
>>> print("python"*3.7)
>>> print("This will not print")
This is concatenation of string
TypeError Traceback (most recent call last)
<ipython-input-15-6eae2c361731> in <module>()
6 print(3*"3")
----> 8 print("python"*3.7)
10 print("This will not print")

TypeError: can't multiply sequence by non-int of type 'float'

## string formatting
# It provides a powerful way of embedding non-strings with strings>>> py_ver = "We are using Python version {}.{}.x".format(3,6)
>>> print(py_ver)
>>> other_version = 2.7
>>> print(f"We could have also used Python {other_version}") # another way of performing string formatting
>>> print("{0}{1}{0}".format("abra ","cad"))We are using Python version 3.6.x
We could have also used Python 2.7
abra cadabra

Useful Pythonic Functions

# strings>>> print(",".join(["NASA","Google","Netflix","Yahoo"]))>>> print("NASA-Google-Netflix-Yahoo".split("-"))>>> print("Python 2.7".replace("2.7","3.6"))>>> print("There is more to it than meets the eye".startswith("There")) # also endswith is there>>> print("python".upper())NASA,Google,Netflix,Yahoo
['NASA', 'Google', 'Netflix', 'Yahoo']
Python 3.6
# numeric>>> print(max(10,64,86,13,98))
>>> print(abs(-9))
>>> print(sum([2,4,6,8]))

User Input Function

There is no raw_input function in Python 3 as available in Python 2. By default, it expects string input.

# user input
data_input = int(input(“Enter your ID: “))
print(“Employee having ID No: {} is late for office today.”.format(data_input))
Enter your ID: 7547857824
<class 'int'>
Employee having ID No: 7547857824 is late for office today.
# multiple inputs in a single entry
var_1, var_2 = input("Enter your name: ").split("-")
Enter your name: bruce-wayne
# another way of performing the same thing mentioned above
name_var = input("Enter your name: ").split(" ")
Enter your name: bruce martha wayne

User-Defined Function

Before going ahead, can you tell me the difference between a function and a method? Well, here is the answer.

Create your own functions using def keyword.

UDF can either take or don’t take arguments. Technically, parameters are the variables in a function definition, and arguments are the values placed to the parameters when the function is called.

The name of the UDF should be lowercase.

NOTE: You must define functions before they are called, in the same way you declare a variable before using them

>>> def udf_1(rqrdArg):
>>> def udf_2(optnlArg = None):
print("OptionalArg: ", optnlArg)

>>> def udf_3(rqrdArg, optnlArg=None, *args, **kwargs): # *args = extra unnamed argument, **kwargs = extra named arguments
print("RequiredArg: ", rqrdArg)
print("OptionalArg: ", optnlArg)
print("Remaining Non-keyworded args: ",args)
print("Remaining keyworded args: ",kwargs)
>>> print("Calling UDF 1!")
>>> print("RequiredArg: ", udf_1(5.7))
>>> print("\nCalling UDF 2!")
>>> udf_2()
>>> udf_2(9)
>>> print("\nCalling UDF 3!")
>>> udf_3("Python","3.6",2,7,MSU_Python_Session=1)

Calling UDF 1!
RequiredArg: 17.1

Calling UDF 2!
OptionalArg: None
OptionalArg: 9

Calling UDF 3!
RequiredArg: Python
OptionalArg: 3.6
Remaining Non-keyworded args: (2, 7)
Remaining keyworded args: {'MSU_Python_Session': 1}

*args and **kwargs allow one to pass a variable-length argument list and keyworded, variable-length argument dictionary respectively to a function when one doesn’t know beforehand how many arguments can be passed to the function.

>>> def UDF_factorial(x):
This is a recursive function performing factorial of a number
x -> the number whose factorial is calculated
if x == 1:
return 1
return x * UDF_factorial(x-1)

>>> print(UDF_factorial(5))
# how to check the function's docstring in notebook>>> ?UDF_factorial # (and execute)

Scope of a variable

Not all variables are accessible from all parts of our program, and not all variables exist for the same amount of time.

Basically, part of a program where a variable is accessible is its scope and the duration for which the variable exists its lifetime.

There are two types of variable scope:

  • Global: It is defined in the main body of a file, will be visible throughout the file, and also inside any file which imports that file.
  • Local: it is defined inside a function, limiting its availability inside that function. It is accessible from the point at which it is defined until the end of the function, and exists for as long as the function is executing.

In Python 3, a third type of variable scope has been defined — nonlocal. It allows to assign variables in an outer, but non-global, scope.

# example showing global, local and nonlocal scopes# global and local
>>> x = "global"
>>> def foo():
print("x inside :", x)
>>> foo()
>>> print("x outside:", x)
x inside : global
x outside: global
>>> def outside():
msg = "Outside!"
def inside():
msg = "Inside!"

>>> outside()

msg is declared in the outside function and assigned the value “Outside!”. Then, in the inside function, the value “Inside!” is assigned to it.

When we run outside, msg has the value “Inside!” in the inside function, but retains the old value in the outside function.

We see this behaviour because Python hasn’t actually assigned new value “Inside” to the existing msg variable, but has created a new variable called msg in the local scope of inside that shadows the name of the variable in the outer scope.

Preventing that behaviour is where the nonlocal keyword comes in.

>>> def double_outside():
msg = "Double Outside!"
def outside():
msg = "Outside!"
def inside():
nonlocal msg
msg = "Inside!"

>>> double_outside()
Double Outside!

Now, by adding nonlocal msg to the top of inside, Python knows that when it sees an assignment to msg, it should assign to the variable from the outer scope instead of declaring a new variable that shadows its name.

The usage of nonlocal is very similar to that of global, except that the former is used for variables in outer function scopes and the latter is used for variable in the global scope.

Additional Read

This is enough for the first part! I hope you guys have liked this article. Give it a clap and we will meet in the 2nd part of this series.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store