0% found this document useful (0 votes)
95 views

Python3 Theory

This document provides an introduction to Python3 programming concepts including: - Comments are used to provide context and ignore code lines - The print() function outputs text to the screen - Variables store and reuse data using the = assignment operator - Errors like SyntaxError and NameError occur when code is invalid or variables are undefined - Python has different data types including strings, numbers, booleans, lists, and dictionaries - Operators perform operations and comparisons on variables

Uploaded by

tomtang77
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
95 views

Python3 Theory

This document provides an introduction to Python3 programming concepts including: - Comments are used to provide context and ignore code lines - The print() function outputs text to the screen - Variables store and reuse data using the = assignment operator - Errors like SyntaxError and NameError occur when code is invalid or variables are undefined - Python has different data types including strings, numbers, booleans, lists, and dictionaries - Operators perform operations and comparisons on variables

Uploaded by

tomtang77
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

PYTHON3 THEORY

BASICS, INTERMEDIATE & ADVANCE

ABOUT THE TRAINER

SAGAR DHAWAN || CCNA, CCNP, DEVNET


+91 9739521088
http://www.networkjourney.com/get-full-
course-content-videos/
https://wa.me/919739521088
PYTHON3 SYNTAX
1. COMMENTS

Comments

Ironically, the first thing we're going to do is show how to tell a computer to ignore a part of a program. Text written in a program but not run by the computer is called
a comment. Python interprets anything after a # as a comment.

Comments can:

Provide context for why something is written the way it is:

# This variable will be used to count the number of times anyone tweets the word persnickety
persnickety_count = 0

Help other people reading the code understand it faster:

# This code will calculate the likelihood that it will rain tomorrow
complicated_rain_calculation_for_tomorrow()

Ignore a line of code and see how a program will run without it:

# useful_value = old_sloppy_code()
useful_value = new_clean_code()
2 PRINT

Print

Now what we're going to do is teach our computer to communicate. The gift of speech is valuable: a computer can answer many questions we have about "how" or "why" or
"what" it is doing. In Python, the print() function is used to tell a computer to talk. The message to be printed should be surrounded by quotes:

# from Mary Shelley's Frankenstein


print("There is something at work in my soul, which I do not understand.")

In the above example, we direct our program to print() an excerpt from a notable book. The printed words that appear as a result of the print() function are referred to
as output. The output of this example program would be:

There is something at work in my soul, which I do not understand.


3. VARIABLES

Programming languages offer a method of storing data for reuse. If there is a greeting we want to present, a date we need to reuse, or a user ID we need to remember we can
create a variable which can store a value. In Python, we assign variables by using the equals sign (=).

message_string = "Hello there"


# Prints ("Hello there“)
print(message_string)

In the above example, we store the message "Hello there" in a variable called message_string.
Variables can't have spaces or symbols in their names other than an underscore (_). They can't begin with numbers but they can have numbers after the first letter
(e.g., cool_variable_5 is OK).

It's no coincidence we call these creatures "variables". If the context of a program changes, we can update a variable but perform the same logical process on it.

# Greeting
message_string = "Hello there"
print(message_string)

# Farewell
message_string = "Hasta la vista"
print(message_string)

Above, we create the variable message_string, assign a welcome message, and print the greeting. After we greet the user, we want to wish them goodbye. We then
update message_string to a departure message and print that out.
4. ERRORS

Humans are prone to making mistakes. Humans are also typically in charge of creating computer programs. To compensate, programming languages attempt to understand
and explain mistakes made in their programs.

Python refers to these mistakes as errors and will point to the location where an error occurred with a ^ character. When programs throw errors that we didn't expect to
encounter we call those errors bugs. Programmers call the process of updating the program so that it no longer produces unexpected errors debugging.

Two common errors that we encounter while writing Python are SyntaxError and NameError.

SyntaxError means there is something wrong with the way your program is written — punctuation that does not belong, a command where it is not expected, or a missing
parenthesis can all trigger a SyntaxError.

A NameError occurs when the Python interpreter sees a word it does not recognize. Code that contains something that looks like a variable but was never defined will throw
a NameError.

Example:
print('This message has mismatched quote marks!") #nameerror
print(Abracadabra) #syntaxerror
5. Python Data Type

In programming, data type is an important concept. x=5


print(type(x))
Variables can store data of different types, and different types can do
different things. x = 20.5
#display x:
Python has the following data types built-in by default, in these print(x)
categories: #display the data type of x: float
print(type(x))
Text Type: str x = {"name" : "John", "age" : 36}
Numeric Types: int, float, complex #display x:
Sequence Types: list, tuple, range print(x)
Mapping Type: dict #display the data type of x:
Set Types: set, frozenset print(type(x))
Boolean Type: bool
Binary Types: bytes, bytearray, memoryview

You can get the data type of any object by using the type() function

Example:
6. Python Strings

String literals in python are surrounded by either single quotation marks, In Python a string is either surrounded by double quotes ("Hello world") or
or double quotation marks. single quotes ('Hello world'). It doesn't matter which kind you use, just be
consistent.
'hello' is the same as "hello".

Example:

print("Hello")
print('Hello’)

Assign a string to Variable

a = "Hello"
print(a)

Computer programmers refer to blocks of text as strings. In our last


exercise, we created the string "Hello world!".
7. Python Numbers

There are three numeric types in Python: containing one or more decimals.
x = 1.10
int y = 1.0
z = -35.59

float print(type(x))
print(type(y))
complex print(type(z))

Examples Complex numbers are written with a "j" as the imaginary part:

Int, or integer, is a whole number, positive or negative, without decimals, x = 3+5j


of unlimited length. y = 5j
x=1 z = -5j
y = 35656222554887711
z = -3255522 print(type(x))
print(type(y))
print(type(x)) print(type(z))
print(type(y))
print(type(z))

Float, or "floating point number" is a number, positive or negative,


8. Python Booleans

Booleans represent one of two values: True or False.

In programming you often need to know if an expression is True or False.

Example 1:

print(10 > 9)
print(10 == 9)
print(10 < 9)

Example 2:

a = 200
b = 33

if b > a:
print("b is greater than a")
else:
print("b is not greater than a")
9 Python Operators

Operators are used to perform operations on variables and


values.

Python divides the operators in the following groups:


- Arithmetic operators
- Assignment operators
- Comparison operators
- Logical operators
- Identity operators
- Membership operators
- Bitwise operators
Example for Identity Operators

Identity “is” examples: Identity “is not” examples:


x = [”ccna", ”ccnp"]
x = ["apple", "banana"]
y = [”ccna", ”ccnp"]
y = ["apple", "banana"]
z=x
z=x
print(x is z)
# returns True because z is the same object as x print(x is not z)
# returns False because z is the same object as x
print(x is y)
# returns False because x is not the same object as y, even if they have the
print(x is not y)
same content # returns True because x is not the same object as y, even if they have the
same content
print(x == y)
# to demonstrate the difference betweeen "is" and "==": this comparison print(x != y)
returns True because x is equal to y \\# to demonstrate the difference betweeen "is not" and "!=": this
comparison returns False because x is equal to y
Example for “in”

x = ["CCNA", "CCNP"]

print("CCNA" in x)
# returns True because a sequence with the value "CCNA" is in the list

Example for “not in”

x = ["CCNA", "CCNP"]

print("CCIE" not in x)
# returns True because a sequence with the value "CCIE" is not in the list
10 Python Lists

Python Collections (Arrays) Check if Item Exists


There are four collection data types in the Python programming language: Example:
List is a collection which is ordered and changeable. Allows duplicate members. thislist = ["apple", "banana", "cherry"]
Tuple is a collection which is ordered and unchangeable. Allows duplicate if "apple" in thislist:
members. print("Yes, 'apple' is in the fruits list")
Set is a collection which is unordered and unindexed. No duplicate members.
Dictionary is a collection which is unordered, changeable and indexed. No
duplicate members. List Length
Example:
thislist = ["apple", "banana", "cherry"]
List: print(len(thislist))
A list is a collection which is ordered and changeable. In Python lists are written
with square brackets.
Example: create a list Add Items
thislist = ["apple", "banana", "cherry"] Example:
print(thislist) thislist = ["apple", "banana", "cherry"]
thislist.append("orange")
print(thislist)
Access Items
Example:
thislist = ["apple", "banana", "cherry"] Join Two Lists
thislist[1] = "blackcurrant" Example:
print(thislist) list1 = ["a", "b" , "c"]
list2 = [1, 2, 3]

Loop Through a List list3 = list1 + list2


Example: print(list3)
thislist = ["apple", "banana", "cherry"]
for x in thislist:
print(x)
11 Python Tuples
Tuple Change Tuple Values
A tuple is a collection which is ordered and unchangeable, indexable. In Python tuples are Once a tuple is created, you cannot change its values. Tuples are unchangeable, or immutable
written with round brackets. as it also is called.
Example: But there is a workaround. You can convert the tuple into a list, change the list, and convert
thistuple = (”ccna", ”ccnp", ”ccie") the list back into a tuple.
print(thistuple) Example:
x = (”ccna", ”ccnp", ”ccie")
y = list(x)
Access Tuple Items y[1] = "automation"
You can access tuple items by referring to the index number, inside square brackets: x = tuple(y)
Example: print(x)
thistuple = ("apple", "banana", "cherry")
print(thistuple[1])
Loop Through a Tuple
You can loop through the tuple items by using a for loop.
Negative Indexing Example:
Negative indexing means beginning from the end, -1 refers to the last item, -2 refers to the thistuple = ("apple", "banana", "cherry")
second last item etc. for x in thistuple:
Example: print(x)
thistuple = ("apple", "banana", "cherry")
print(thistuple[-1])
Check if Item Exists
To determine if a specified item is present in a tuple use the in keyword:
Range of Indexes Example:
You can specify a range of indexes by specifying where to start and where to end the range. thistuple = ("apple", "banana", "cherry")
When specifying a range, the return value will be a new tuple with the specified items. if "apple" in thistuple:
thistuple = ("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango") print("Yes, 'apple' is in the fruits tuple")
print(thistuple[2:5])

Tuple Length
Range of Negative Indexes To determine how many items a tuple has, use the len() method:
Specify negative indexes if you want to start the search from the end of the tuple: Example:
Example: thistuple = ("apple", "banana", "cherry")
This example returns the items from index -4 (included) to index -1 (excluded) print(len(thistuple))
thistuple = ("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
print(thistuple[-4:-1])
12 Python Sets
Set Add multiple items to a set, using the update() method:
A set is a collection which is unordered and unindexed. In Python sets are written with curly thisset = {"apple", "banana", "cherry"}
brackets. thisset.update(["orange", "mango", "grapes"])
Example: print(thisset)
thisset = {"apple", "banana", "cherry"}
print(thisset)
Note: Sets are unordered, so you cannot be sure in which order the items will appear. Get the Length of a Set
thisset = {"apple", "banana", "cherry"}

Access Items print(len(thisset))


You cannot access items in a set by referring to an index, since sets are unordered the items has
no index.
But you can loop through the set items using a for loop, or ask if a specified value is present in a Remove Item
set, by using the in keyword. thisset = {"apple", "banana", "cherry"}
Example:
thisset = {"apple", "banana", "cherry"} thisset.remove("banana")
for x in thisset:
print(x) print(thisset)
Note: If the item to remove does not exist, remove() will raise an error.

Example
Check if "banana" is present in the set: thisset = {"apple", "banana", "cherry"}
thisset = {"apple", "banana", "cherry"}
print("banana" in thisset) thisset.discard("banana")

print(thisset)
Change Items Note: If the item to remove does not exist, discard() will NOT raise an error.
Once a set is created, you cannot change its items, but you can add new items.
Join Two Sets
Add Items set1 = {"a", "b" , "c"}
To add one item to a set use the add() method. set2 = {1, 2, 3}
To add more than one item to a set use the update() method.
Example: set3 = set1.union(set2)
thisset = {"apple", "banana", "cherry"} print(set3)
thisset.add("orange")
print(thisset)
Note: You can use the union() method that returns a new set containing all items from both sets,
or the update() method that inserts all the items from one set into another:
13 Python Dictionaries
A dictionary is a collection which is unordered, changeable and indexed. In Python dictionaries are if "model" in thisdict:
written with curly brackets, and they have keys and values. print("Yes, 'model' is one of the keys in the thisdict dictionary")
Example:
thisdict = {
"brand": "Ford", Dictionary Length
"model": "Mustang", Example:
"year": 1964 print(len(thisdict))
}
print(thisdict)
Nested Dictionaries
A dictionary can also contain many dictionaries, this is called nested dictionaries.
Accessing Items Example:
You can access the items of a dictionary by referring to its key name, inside square brackets: myfamily = {
Example: "child1" : {
x = thisdict["model"] "name" : "Emil",
There is also a method called get() that will give you the same result: "year" : 2004
Example: },
x = thisdict.get("model") "child2" : {
"name" : "Tobias",
"year" : 2007
Change Values },
You can change the value of a specific item by referring to its key name: "child3" : {
Example: "name" : "Linus",
thisdict = { "year" : 2011
"brand": "Ford", }
"model": "Mustang", }
"year": 1964
}
thisdict["year"] = 2018 Adding Items
Adding an item to the dictionary is done by using a new index key and assigning a value to it:
Example:
Check if Key Exists thisdict = {
"brand": "Ford",
"model": "Mustang",
Example: "year": 1964
thisdict = { }
"brand": "Ford", thisdict["color"] = "red"
"model": "Mustang", print(thisdict)
"year": 1964
}
14. Python Casting

There may be times when you want to specify a type on to a Example:


variable. This can be done with casting. Python is an object- x = int(1)
orientated language, and as such it uses classes to define data y = int(2.8)
types, including its primitive types. z = int("3")
print(x)
Casting in python is therefore done using constructor functions: print(y)
print(z)
int() - constructs an integer number from an integer literal, a
float literal (by rounding down to the previous whole number), or Example:
a string literal (providing the string represents a whole number) x = int(1) # x will be 1
y = int(2.8) # y will be 2
z = int("3") # z will be 3
float() - constructs a float number from an integer literal, a float
literal or a string literal (providing the string represents a float or
an integer)

str() - constructs a string from a wide variety of data types,


including strings, integer literals and float literals
15 Python Conditions and If statements
Python supports the usual logical conditions from mathematics: print("b is greater than a")
elif a == b:
Equals: a == b print("a and b are equal")
Not Equals: a != b else:
Less than: a < b print("a is greater than b")
Less than or equal to: a <= b
Greater than: a > b Example2:
Greater than or equal to: a >= b a = 200
b = 33
if b > a:
Example: print("b is greater than a")
a = 33 else:
b = 200 print("b is not greater than a")
if b > a:
print("b is greater than a")
And
a = 200
Indentation b = 33
Python relies on indentation (whitespace at the beginning of a line) to define scope in the code. Other c = 500
programming languages often use curly-brackets for this purpose. if a > b and c > a:
a = 33 print("Both conditions are True")
b = 200
if b > a:
print("b is greater than a") # you will get an error Or
a = 200
b = 33
Elif c = 500
The elif keyword is pythons way of saying "if the previous conditions were not true, then try this condition". if a > b or a > c:
a = 33 print("At least one of the conditions is True")
b = 33
if b > a:
print("b is greater than a") Nested If
elif a == b: x = 41
print("a and b are equal")
if x > 10:
print("Above ten,")
Else if x > 20:
The else keyword catches anything which isn't caught by the preceding conditions. print("and also above 20!")
a = 200 else:
b = 33 print("but not above 20.")
if b > a:
16. Python While Loops
Python Loops i += 1
Python has two primitive loop commands:
1. while loops The continue Statement
2. for loops With the continue statement we can stop the current iteration, and
continue with the next:
The While Loop i=0
i=1 while i < 6:
while i < 6: i += 1
print(i) if i == 3:
i += 1 continue
Note: remember to increment i, or else the loop will continue print(i)
forever.
The while loop requires relevant variables to be ready, in this The else Statement
example we need to define an indexing variable, i, which we set to With the else statement we can run a block of code once when the
1. condition no longer is true:
i=1
The break Statement while i < 6:
With the break statement we can stop the loop even if the while print(i)
condition is true: i += 1
i=1 else:
while i < 6: print("i is no longer less than 6")
print(i)
if i == 3:
break
17. Python For Loops
A for loop is used for iterating over a sequence (that is either a list, a tuple, a dictionary, a set, or a The range() Function
string). To loop through a set of code a specified number of times, we can use the range() function,
fruits = ["apple", "banana", "cherry"] The range() function returns a sequence of numbers, starting from 0 by default, and increments by 1
for x in fruits: (by default), and ends at a specified number.
print(x) Example1:
for x in range(6):
print(x)
Looping Through a String Example2:
for x in "banana": for x in range(2, 6):
print(x) print(x)

The break Statement Increment the sequence with 3 (default is 1):


With the break statement we can stop the loop before it has looped through all the items: for x in range(2, 30, 3):
fruits = ["apple", "banana", "cherry"] print(x)
for x in fruits:
print(x)
if x == "banana": Else in For Loop
break for x in range(6):
print(x)
else:
Exit the loop when x is "banana", but this time the break comes before the print: print("Finally finished!")
fruits = ["apple", "banana", "cherry"]
for x in fruits:
if x == "banana": Nested Loops
break A nested loop is a loop inside a loop.
print(x) The "inner loop" will be executed one time for each iteration of the "outer loop":
adj = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]
The continue Statement
With the continue statement we can stop the current iteration of the loop, and continue with the next: for x in adj:
fruits = ["apple", "banana", "cherry"] for y in fruits:
for x in fruits: print(x, y)
if x == "banana":
continue
print(x)
18. Python Functions
A function is a block of code which only runs when it is called. Arguments are often shortened to args in Python documentations.
You can pass data, known as parameters, into a function.
A function can return data as a result.
The terms parameter and argument can be used for the same thing: information that are
passed into a function.
STEP#1: Creating a Function
def my_function():
print("Hello from a function") Number of Arguments
By default, a function must be called with the correct number of arguments. Meaning that if
your function expects 2 arguments, you have to call the function with 2 arguments, not more,
STEP#2: Calling a Function and not less.
def my_function():
print("Hello from a function")

my_function()

Arguments
Information can be passed into functions as arguments. Arbitrary Arguments, *args
Arguments are specified after the function name, inside the parentheses. You can add as many If you do not know how many arguments that will be passed into your function, add a * before
arguments as you want, just separate them with a comma. the parameter name in the function definition.
The following example has a function with one argument (arg). def my_function(*network):
Example: print("this is youngest " + network[1])
def my_function(arg): my_function("ccna", "ccnp", "ccie")
print(arg + " NETWORKING“)
my_function("CCNA")
my_function("CCNP") Arbitrary Keyword Arguments, **kwargs
my_function("CCIE") If you do not know how many keyword arguments that will be passed into your function, add
two asterisk: ** before the parameter name in the function definition.
def my_function(**network):
print("This is network program " + network["intermediate"])
my_function(basic = "CCNA", intermediate = "CCNP")
19. Python Modules
What is a Module? Built-in Modules
Consider a module to be the same as a code library. There are several built-in modules in Python, which you can import whenever you like.
A file containing a set of functions you want to include in your application. import platform
x = platform.system()
print(x)
Step#1: Create a Module
To create a module just save the code you want in a file with the file extension .py:
Import From Module:
The module named mymodule has one function and one dictionary:
mymodule.py mymodule.py
def greeting(name):
print("Hello, " + name)

Step#2: Use a Module

import mymodule
mymodule.greeting("NETWORK AUTOMATION")

Variables in Module
The module can contain functions, as already described, but also variables of all types (arrays,
dictionaries, objects etc):

mymodule.py

Use a module
20. Python RegEx

A RegEx, or Regular Expression, is a sequence of characters that forms a search pattern. import re
RegEx can be used to check if a string contains the specified search pattern. txt = "The rain in Spain“
x = re.findall("ai", txt)
print(x)
RegEx Module
Python has a built-in package called re, which can be used to work with Regular
Expressions. The search() Function
The search() function searches the string for a match, and returns a Match object if there is
a match.
Import the re module:
import re If there is more than one match, only the first occurrence of the match will be returned:

RegEx in Python
When you have imported the re module, you can start using regular expressions: The search() Function
The search() function searches the string for a match, and returns a Match object if there is
a match.
If there is more than one match, only the first occurrence of the match will be returned:
import re
txt = "The rain in Spain“
x = re.search("r", txt)
print(“The first white-space character is located in position:", x.start())

The findall() Function


21. Python PIP

What is PIP? Once the package is installed, it is ready to use.


PIP is a package manager for Python packages, or modules if you like. Import the "camelcase" package into your project.
import netmiko
Note: If you have Python version 3.4 or later, PIP is included by default.
Remove a Package
Use the uninstall command to remove a package:
What is a Package? C:\Users\Your Name\AppData\Local\Programs\Python\Python36-32\Scripts>pip
A package contains all the files you need for a module. uninstall netmiko
Modules are Python code libraries you can include in your project.
List Packages
Check if PIP is Installed Use the list command to list all the packages installed on your system:
Check PIP version: C:\Users\Your Name\AppData\Local\Programs\Python\Python36-32\Scripts>pip list
C:\Users\Your Name\AppData\Local\Programs\Python\Python36-32\Scripts>pip --
version

Install PIP
If you do not have PIP installed, you can download and install it from this page:
https://pypi.org/project/pip/

Download a Package
Downloading a package is very easy.
Open the command line interface and tell PIP to download the package you want.
C:\Users\Your Name\AppData\Local\Programs\Python\Python36-32\Scripts>pip install
netmiko

Using a Package
22. Python Try Except (Error Handling)

The try block lets you test a block of code for errors. Finally
The except block lets you handle the error.
The finally block lets you execute code, regardless of the result of the try- and except
blocks. The finally block, if specified, will be executed regardless if the try block raises an error
or not.
Exception Handling
When an error occurs, or exception as we call it, Python will normally stop and
generate an error message.
These exceptions can be handled using the try statement:
try:
print(x)
except:
print("An exception occurred")

Many Exceptions
You can define as many exception blocks as you want, e.g. if you want to execute a
special block of code for a special kind of error:
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")
23. Python User Input

Python allows for user input. PYTHON 3.x


That means we are able to ask the user for input. username = input("Enter username:")
print("Username is: " + username)
The method is a bit different in Python 3.6 than
Python 2.7. PYTHON 2.x
Python 3.6 uses the input() method. username = raw_input("Enter username:")
print("Username is: " + username)
Python 2.7 uses the raw_input() method.
24. Python JSON JavaScript Object Notation
- JSON is a syntax for storing and exchanging data. # convert into JSON:
- JSON is text, written with JavaScript object notation. y = json.dumps(x)
# the result is a JSON string:
print(y)
Python has a built-in package called json, which can be used to work with JSON data.
import json You can convert Python objects of the following types, into JSON strings:
Dict
List
Parse JSON - Convert from JSON to Python Tuple
If you have a JSON string, you can parse it by using the json.loads() method. String
The result will be a Python dictionary. Int
Example: Float
import json True
# some JSON: False
x = '{ "name":"John", "age":30, "city":"New York"}’ None
# parse x: Example:
y = json.loads(x) import json
# the result is a Python dictionary:
print(y["age"]) print(json.dumps({"name": "John", "age": 30}))
print(json.dumps([”ccna", ”ccnp"]))
print(json.dumps((”ccna", ”ccnp")))
Convert from Python to JSON print(json.dumps("hello"))
If you have a Python object, you can convert it into a JSON string by using the print(json.dumps(42))
json.dumps() method. print(json.dumps(31.76))
Example: print(json.dumps(True))
import json print(json.dumps(False))
# a Python object (dict): print(json.dumps(None))
x={
"name": "John", - next page contd.
"age": 30,
"city": "New York"
}
Format the Result
The example above prints a JSON string, but it is not very easy to read, with no indentations
and line breaks.

The json.dumps() method has parameters to make it easier to read the result:

Example:
json.dumps(x, indent=4)

Example:
import json
x={
"name": "John",
"age": 30,
"married": True,
"divorced": False,
"children": ("Ann","Billy"),
"pets": None,
"cars": [
{"model": "BMW 230", "mpg": 27.5},
{"model": "Ford Edge", "mpg": 24.1}
]
}
# use four indents to make it easier to read the result:
print(json.dumps(x, indent=4))

You might also like