Python | PDF | Data Type | Parameter (Computer Programming)
0% found this document useful (0 votes)
3 views66 pages

Python

A computer language is a medium for interacting with computers, categorized into machine languages, assembly languages, and various programming languages. Compiled languages translate source code into machine code for faster execution, while interpreted languages execute code line-by-line without prior compilation. Python, a high-level language, is both compiled and interpreted, featuring dynamic typing, garbage collection, and extensive libraries, making it user-friendly and versatile.

Uploaded by

Isha Shinde
Copyright
© © All Rights Reserved
Available Formats
Download as ODT, PDF, TXT or read online on Scribd
Download as odt, pdf, or txt
0% found this document useful (0 votes)
3 views66 pages

Python

A computer language is a medium for interacting with computers, categorized into machine languages, assembly languages, and various programming languages. Compiled languages translate source code into machine code for faster execution, while interpreted languages execute code line-by-line without prior compilation. Python, a high-level language, is both compiled and interpreted, featuring dynamic typing, garbage collection, and extensive libraries, making it user-friendly and versatile.

Uploaded by

Isha Shinde
Copyright
© © All Rights Reserved
Available Formats
Download as ODT, PDF, TXT or read online on Scribd
Download as odt, pdf, or txt
Download as odt, pdf, or txt
You are on page 1/ 66

What is a computer language?

A computer language is a medium used to interact with computers and solve problems by writing
programs. There are several types:
1. Machine Languages: Binary code (0s and 1s) directly executed by the CPU.
2. Assembly Languages: Low-level language closely related to one or a family of machine
languages, and which uses mnemonics to ease writing. Assembly language is specific to a
computer's architecture, meaning each family of machines(e.g x86 Family: Intel 8086,
Pentium, AMD processors (PCs, laptops); ARM Family: ARM Cortex series (mobile,
embedded systems); MIPS Family: Embedded devices, routers (networking, embedded
systems); SPARC Family: Sun Microsystems servers (enterprise servers); IBM System/360
Family: IBM mainframes (business, scientific computing).) has its own assembly language.

Key Differences
• Readability: Binary language is nearly impossible for humans to read, while assembly
language uses more understandable mnemonics.
• Translation: Binary is executed directly by the CPU; assembly needs to be converted
into binary by an assembler.
• Ease of Use: Assembly language is easier for programmers to use and debug compared
to binary.
• Abstraction Level: Binary language is at the lowest level of abstraction, directly dealing
with hardware. Assembly language offers a slightly higher level of abstraction with more
human-readable instructions.

3. Programming Languages:
• General Purpose Languages: Broadly applicable across domains and lacks
specialized features for a particular domain(e.g., Python, Java, C).
• Markup Languages: Used for annotating documents in a syntactically
distinguishable way from the text (e.g., HTML, XML).
• Stylesheet Languages: Express document presentation (e.g., CSS).
• Configuration Languages: Write configuration files (e.g., JSON).
• Query Languages: Make queries in databases (e.g., SQL).
• Scripting Languages: Write scripts (e.g., JavaScript, Ruby).
Low Level vs High Level Languages

Compiled language
A compiled language is one where the source code is translated into machine code by a compiler,
resulting in faster execution and thorough error checking before running the program. This machine
code is directly executed by the computer's CPU. E.g. C, C++, Pascal, Objective-C, Swift, Go,
Rust, and Fortran

Characteristics of Compiled Languages


1. Compilation Process: Source code is translated into machine code by a compiler. The
resulting machine code is a standalone executable file.
2. Performance: Generally faster execution compared to interpreted languages because the
machine code is optimized for the target hardware.
3. Error Checking: Errors are caught during the compilation process, which can prevent
runtime errors.
4. Portability: Compiled code is typically platform-specific; it needs to be recompiled for
different architectures or operating systems.
5. Execution: The compiled program runs directly on the hardware without needing an
interpreter.

Stages compilation process:

1. Pre-processing (main.c)
• Purpose: To prepare the source code for compilation.
• Strips out comments from the code, which are not needed for execution.
• Expands macros and includes header files as specified by #include directives.
• Includes or excludes parts of the code based on preprocessor directives (e.g., #ifdef,
#ifndef, #if).

2. Compiling (main.i)
• Purpose: To translate pre-processed code into assembly instructions.
• The compiler converts the pre-processed code into assembly language, which is specific to
the target processor architecture.
3. Assembling (main.s)
• Purpose: To convert assembly instructions into object code.
• The assembler translates the assembly language code into machine code (object code),
which is a binary representation that the computer's CPU can execute.
4. Linking (a.out or main.exe)
• Purpose: To produce the final executable file.
• The linker combines object code files, resolves references between them, and inserts code
from libraries or other modules as needed. It arranges the code and data into a cohesive
executable file.
Interpreted Language
An interpreted language is a type of programming language where instructions are executed directly
without the need for compilation into machine code. Here are the key characteristics of interpreted
languages:

Characteristics of Interpreted Languages


1. Execution: Instructions are executed line-by-line by an interpreter. An interpreter translates
one statement of programming code at a time into machine code.
2. No Compilation: Source code is not translated into machine code before execution.
3. Portability: Generally more portable than compiled languages because the interpreter itself
can run on different platforms.
4. Debugging: Easier debugging as errors are often reported as they occur during execution.
5. Slower Execution: Typically slower than compiled languages because each statement is
translated and executed at runtime.
6. Examples: Common interpreted languages include Python, JavaScript, Ruby, PHP, and Perl.

How Interpreted Languages Work


• Interpreter: Reads the source code, translates each statement into machine-understandable
instructions (bytecode or intermediate code), and then executes them immediately.
• No Intermediate Executable: Unlike compiled languages, interpreted languages do not
produce a standalone executable file; the source code remains as the primary form of the
program.

Advantages and Disadvantages


• Advantages: Quick development cycle, platform independence, interactive debugging.
• Disadvantages: Slower execution speed compared to compiled languages, less optimization
potential.

Example:
In Python, for instance, you can write a script (script.py) directly in the Python interpreter or
run it using python script.py, where the Python interpreter reads and executes each line of
code without needing a separate compilation step.

Mixed language: shows behavior from both (compiled as well as interpreted) uses compiler as
well as interpreter e.g. Java, Python
Compiler vs Interpreter

------------------------------------------------------------------------------------------------
Python
• Python was conceived by Guido van Rossum in the late 1980s as a successor to the ABC
language. Development started in December 1989, and van Rossum led the project until July
2018. A team of five then took over in January 2019.
• python application does NOT require any entry point function
• python is one of the scripting languages. The code starts execution from from top (line 1) to
bottom
• Python is a general-purpose, high-level, and compiled as well as interpreted language with
the following characteristics:
• Dynamically Typed: Variables do not require explicit type definitions.
• Garbage Collected: Automatically manages memory by cleaning up unused objects.

• Supports Multiple Paradigms:



Procedural Programming: Writing scripts and functions.

Object-Oriented Programming: Using classes and objects.

Functional Programming: Employing functions as first-class citizens.

Aspect-Oriented Programming: Includes features like metaprogramming and
magic methods.
• Readable Syntax: Relies on indentation to define code blocks, enhancing readability.
• Extensive Libraries: Over 300,000 packages available for diverse functionalities.
Examples of Python Packages:
• Tkinter: For graphical user interfaces.
• Flask/Django: For web frameworks.
• Socket: For networking.
• Selenium: For automation.
• Scrapy/BeautifulSoup: For web scraping.

Advantages of Python:
• Ease of Use: Simple and user-friendly, suitable for both beginners and experienced
programmers, offering more structure than shell scripts or batch files.
• Error Checking: Provides more error checking compared to C and includes high-level data
types like flexible arrays and dictionaries.
• Broad Applicability: More versatile than Awk or Perl, capable of handling a wider range of
problems with ease.
• Modularization: Supports splitting programs into reusable modules.
• Interpreted Language: Saves time during development as there's no need for compilation
and linking.
• Compact and Readable: Allows for concise and readable code, with programs often shorter
than equivalent code in C, C++, or Java due to:
• High-level data types for complex operations.
• Indentation for grouping statements instead of brackets.
• No need for variable or argument declarations.

Differences between Python and C Language


Environment Setup
> sudo apt install python3 --Installs the Python 3 interpreter along with the necessary
standard library and support tools
> python3 --version
> sudo apt install python3-pip
> pip3 –version
Pip is the package installer for Python. It allows you to install and manage additional libraries and
dependencies that are not part of the standard Python library. Pip makes it easy to install and
manage Python packages from the Python Package Index (PyPI) and other package repositories.
> pip install package_name

> pip uninstall package_name

> pip install --upgrade package_name

> pip list -- Show Intalled packages


> pip show package_name -- Show Package information

versions
0.9.0: deprecated. Having features like classes with inheritance, exception handling, functions

1.x: deprecated. functional programming tools like lambda, map, filter, reduce

2.x: about to be deprecated. list comprehension, garbage collection, generators etc.

3.x ("Python 3000" or "Py3K”): latest version. Rectify fundamental design


flaws in the language, removing duplicative constructs and modules

How is Python program executed?

1.Writing the Source Code(hello.py file)


def greet(name):
return f"Hello, {name}!"
print(greet("Alice"))

2. Python Compiler: Python interpreter compiles the source code (hello.py) into bytecode.
a. Lexical Analysis: The interpreter reads the source code and breaks it down into tokens.
Tokens are the smallest units of the code, such as keywords, identifiers, literals, and
operators.
Tokens for the Example:
• def
• greet
• (
• name
• )
• :
• return
• f"Hello, {name}!"
• print
• (
• greet
• (
• "Alice"
• )
• )

b. Parsing: The tokens are then organized into a syntax tree (also known as an abstract
syntax tree or AST). The syntax tree represents the structure of the program based on the
syntax rules of Python. The parser checks the syntax tree for correctness. If the code is
syntactically incorrect, Python will produce an error message.
AST Representation:
• Function Definition (greet)
• Parameters (name)
• Body
• Return Statement
• Formatted String (f"Hello, {name}!")
• Print Statement
• Function Call (greet)
• Argument ("Alice")
c. Semantic Analysis
• Type Checking and Validation: Python performs semantic checks, such as verifying
that name is a valid parameter and that print is a callable function.

d. Compilation: The Python interpreter compiles the syntax tree into bytecode. Bytecode
is a low-level representation of your source code that is easier for the interpreter to execute.

3. Bytecode (.pyc)
• OS Independent: The compiled bytecode is saved in a .pyc file. This bytecode is
platform-independent, meaning it can be executed on any operating system that has a
compatible Python interpreter.
• The size of each byte code is 1 byte or 8 bits and hence the these are called as byte codes

4. Python Interpreter
• Execution: The bytecode is executed by the Python Virtual Machine (PVM). interprets the
bytecode and translates it into machine code that can be executed by the CPU.
• OS Dependent: While the bytecode itself is OS-independent, the PVM translates it into OS-
specific machine code.

6. Native Executable (Machine code .asm)


• Integration with OS: The native executable interacts with the operating system to perform
various tasks, such as I/O operations, memory management, etc.
RULE
• if the code has any synctical error, the python compiler will not generate the byte codes [the
syntactical errors will be detected at the time compilation]
print(“hello1”)
print("hello 2" # generate SyntaxError. even the first line will NOT get executed
• if the code has any run time error, the compilation will not detect any error and program will
execute till the line where the error is detected

print("hello 1")
printf("hello 2") #will generate NameError. he first line will get executed and code will stop on the
line
------------------------------------------------------------------------------------------------------------------------

Python Implementations:
• PyPy: Faster alternative due to JIT compilation. Written in Python
• Jython: For Java platform integration.
• IronPython: For .NET framework integration.
• CPython: The default, standard version of Python you get from the official site, widely
used, and written in C. Fastest

Identifiers and Keywords in Python


Identifiers: Names for variables, types, functions, and classes. Most of the times are lower cased
• Rules:
• Must be unique and case-sensitive.
• Cannot be a keyword.
Keywords: Reserved words that cannot be used as names for variables, types, functions, or classes.
• Total Keywords: 35 in Python 3.8.

Categories of Keywords:
1. Value Keywords: True, False, None
2. Operator Keywords: and, or, not, in, is
3. Control Flow Keywords: if, elif, else
4. Iteration Keywords: for, while, break, continue, else
5. Structure Keywords: def, class, with, as, pass, lambda
6. Returning Keywords: return, yield
7. Import Keywords: import, from, as
8. Exception-Handling Keywords: try, except, raise, finally, else, assert
9. Asynchronous Programming Keywords: async, await
10.Variable Handling Keywords: del, global, nonlocal

Rules and Conventions for Identifiers in Python


1. Allowed Characters: Use letters (a-z, A-Z), digits (0-9), or underscores (_).
2. Two-Word Variables: Separate words with an underscore (_).
3. Meaningful Names: Use descriptive and meaningful names.
4. Constants: Use all capital letters for constants.
5. Special Symbols: Avoid symbols like !, @, #, $, %, etc.
6. Starting Characters: Do not start names with a digit.
7. Comments: Use # for comments.
8. Case Sensitivity: Identifiers are case-sensitive.

Valid Identifiers
1. variable1
2. first_name
3. MAX_LIMIT
4. total_amount
5. _private_var
6. userAge

Invalid Identifiers
1. 1variable - Starts with a digit
2. first-name - Contains a hyphen
3. price! - Contains a special symbol !
4. @home - Contains a special symbol @
5. total amount - Contains a space
6. class - Uses a reserved keyword

Conventions
• for variables: lower case e.g. name, address, first_name
• for functions: lower case with underscore e.g. is_eligible_for_voting
• or class: lower case with first letter uppercase e.g. Person, Mobile

Variables
• A named location used to store data in memory.
• Think of variables as containers that hold data that can be changed later.

Characteristics
• Dynamically-Typed: In languages like Python, you do not need to declare the data type of a
variable explicitly. The data type is inferred when a value is assigned to the variable.
value = 20 # Integer
name = "Steve" # String
pi = 3.14 # Float
is_valid = True # Boolean

Key Points
1. No Explicit Type Declaration: The type is inferred from the value assigned.
2. Reassignable: Variables can be reassigned to different types of values.
3. Container Concept: Variables act as containers that can hold different types of data.
# Examples of variable assignments
value = 20 # Initially an integer
value = "twenty" # Now a string

• Logical address is the variable name used in code.


• Physical address is the memory location, accessible using id().

my_variable = "Hello, World!" # Logical Address


print(my_variable) # Output: Hello, World!
physical_address = id(my_variable) # Physical Address
print(physical_address) # Output: Memory address (an integer)

Constants
In Python, constants are indicated by naming variables in all capital letters with underscores
between words. This is a convention to signal that the value should not change, though Python does
not enforce this and allows reassignment.

PI = 3.14 # Define constants


circle_area = PI * radius * radius # Use constants in calculations
PI = 3.14159 # This is allowed in Python but should be avoided
print(PI)

Python Statements
• Statement: An instruction that a Python interpreter can execute.

Types of Statements
1. Assignment Statement: Assigns a value to a variable.
num = 200
2. Single-Line Statement: Ends with a newline character.
a = 1
print(a)

3. Declaration Statement: Variables are declared at the point of


assignment.

age = 25 # Here, age is declared and assigned

4. Function Call: Invokes a function, executing its code block.


def greet(name):
print(f"Hello, {name}!")
greet("Alice") # Function call

5. Control Statement: Directs the flow of control in a program.


• Examples: break, continue, pass, return
for i in range(5):
if i == 3:
break # Control statement to exit the loop
print(i)

6. Conditional Statement: Executes code based on a condition.


• Syntax: if, elif, and else
age = 18
if age >= 18:
print("Adult")
else:
print("Minor")

3. Multi-Line Statement:
• Extend over multiple lines using the line continuation character (\).
• Implied inside parentheses (), brackets [], and braces {}.
total = (1 + 2 +
3 + 4)

• or
total = 1 + 2 + 3 + \

4 + 5 + 6 + \

7 + 8 + 9

4. Multiple Statements in One Line: Use semicolons ; to separate them.


a = 1; b = 2; c = 3

Comments: Use the hash # symbol to start a comment.


num = 200 # This is an inline comment

Data Types
• Data Types: Define the nature of data and operations that can be performed. An attribute
associated with a piece of data that tells a computer system how to interpret its value.

• Dynamic Typing: Type is determined at runtime (e.g., Python, JavaScript).

• Static Typing: Type is determined at compile-time (e.g., C, C++).


Python Data Types

1. Numeric Types:
• Integer: Whole numbers
• Float: Decimal numbers
• Complex: Numbers with real and imaginary parts

2. Boolean Type:
• Boolean: Represents True or False

3. Sequence Types:
• String: Sequence of characters
• List: Ordered, mutable collection
• Tuple: Ordered, immutable collection

4. Set Type:
• Set: Unordered, mutable collection of unique items

5. Dictionary Type:
• Dictionary: Collection of key-value pairs
# Numeric Types
a = 10 # Integer
pi = 3.14 # Float
z = 2 + 3j # Complex
# Boolean Type
is_valid = True # Boolean

# Sequence Types
name = "Alice" # String
fruits = ["apple", "banana", "cherry"] # List
point = (1, 2) # Tuple

# Set Type
unique_numbers = {1, 2, 3, 4, 5} # Set

# Dictionary Type
person = {"name": "John", "age": 30} # Dictionary

Literals
In Python, literals are fixed values that are used directly in code. They represent data without
needing any computation. It is raw data given in a variable or constan
1. Integer Literals: These are whole numbers without a decimal point. They are immutable
• Example: 10, -5, 0
2. Floating-Point Literals: These represent real numbers with a decimal point.
• Example: 3.14, -0.001, 2.0
3. String Literals: These are sequences of characters enclosed in quotes.
• Single quotes: 'hello'
• Double quotes: "world"
• Triple quotes for multi-line strings: '''multi-line string''' or
"""multi-line string"""
4. Boolean Literals: These represent truth values.
• True and False

5. None Literal: This represents the absence of a value or a null value.


• None
6. Complex Literals: These represent complex numbers with real and imaginary parts.
• Example: 3+4j, -2-5j
7. Collection Literals
• List Literals: Example: [1, 2, 3]

• Tuple Literals: Example: (1, 2, 3)

• Dictionary Literals: Example: {'key1':'value1', 'key2':'value2'}

• Set Literals: Example: {1, 2, 3}

Type hinting in Python


Type hinting in Python helps:
1. Type Checkers: Detect type mismatches and potential errors by specifying expected types.
2. Documentation: Clarify the types of function parameters and return values, making code
easier to understand.
3. IDEs: Improve code completion and error detection by providing type information.

Example
def add_numbers(a: int, b: int) -> int:
return a + b

num: int = 100

• a: int and b: int indicate add_numbers expects integers.


• -> int shows it returns an integer.

Type Conversion
Type conversion in Python involves changing the data type of a value to another type.
1. Implicit Type Conversion: Automatic and Avoids any Data Loss
result = 10 + 35.50 # converts 10 (int) to 10.0 (float) before addition

2. Explicit Type Conversion (also called Type Casting):


• Manual: Users explicitly convert data types using predefined functions.
• Functions: Common functions include int(), float(), str(), etc.
• Potential Data Loss: Data loss may occur if converting to a type that can't represent
the original value precisely (e.g., converting a float to an integer).

num_str = str(1024) #Converts the integer 1024 to the string '1024'

String to List:

str_val = "hello"
list_val = list(str_val)
print(list_val) # Output: ['h', 'e', 'l', 'l', 'o']
print(type(list_val)) # Output: <class 'list'>
List to Tuple:
list_val = [1, 2, 3]
tuple_val = tuple(list_val)
print(tuple_val) # Output: (1, 2, 3)
Tuple to Set:
tuple_val = (1, 2, 3, 3)
set_val = set(tuple_val)
print(set_val) # Output: {1, 2, 3}
print(type(set_val)) # Output: <class 'set'>

List of Pairs to Dictionary:


list_pairs = [(1, 'a'), (2, 'b')]
dict_val = dict(list_pairs)
print(dict_val) # Output: {1: 'a', 2: 'b'}
print(type(dict_val)) # Output: <class 'dict'>

Character to ASCII and Vice Versa:


char_val = 'a'
ascii_val = ord(char_val)
print(ascii_val) # Output: 97
print(type(ascii_val)) # Output: <class 'int'>

int_val = 97
char_val = chr(int_val)
print(char_val) # Output: 'a'
print(type(char_val)) # Output: <class 'str'>

1. Integer (int) Conversions

Conversion Example Result Explanation


int to float float(5) 5.0 Converts integer to float.
int to str str(5) '5' Converts integer to string.
int to bool bool(5) True Non-zero integers convert to True.
int to complex complex(5) (5+0j) Converts integer to complex number.
int to list list([5]) [5] Converts integer wrapped in a list.
int to tuple tuple([5]) (5,) Converts integer wrapped in a tuple.
int to set set([5]) {5} Converts integer wrapped in a set.
int to dict dict([(5, 'a')]) {5: 'a'} Converts integer key wrapped in a dict.

2. Float (float) Conversions


Conversion Example Result Explanation
float to int int(5.5) 5 Truncates the decimal part.
float to str str(5.5) '5.5' Converts float to string.
float to bool bool(5.5) True Non-zero floats convert to True.
float to complex complex(5.5) (5.5+0j) Converts float to complex number.
float to list list([5.5]) [5.5] Converts float wrapped in a list.
float to tuple tuple([5.5]) (5.5,) Converts float wrapped in a tuple.
float to set set([5.5]) {5.5} Converts float wrapped in a set.
Conversion Example Result Explanation
float to dict dict([(5.5, 'a')]) {5.5: 'a'} Converts float key wrapped in a dict.

3. String (str) Conversions


Conversion Example Result Explanation
Converts string to integer if
str to int int('5') 5
possible.
Converts string to float if
str to float float('5.5') 5.5
possible.
Non-empty strings convert to
str to bool bool('hello') True
True.
Converts string to complex if
str to complex complex('5+1j') (5+1j)
possible.
str to list list('hello') ['h', 'e', 'l', 'l', 'o'] Converts string to list of
characters.
str to tuple tuple('hello') ('h', 'e', 'l', 'l', 'o') Converts string to tuple of
characters.
Converts string to set of
str to set set('hello') {'h', 'e', 'l', 'o'}
characters.
dict([('a', 1), Converts list of tuples to
str to dict {'a': 1, 'b': 2}
('b', 2)]) dictionary.

4. Boolean (bool) Conversions


Conversion Example Result Explanation
bool to int int(True) 1 True converts to 1, False to 0.
bool to float float(True) 1.0 True converts to 1.0, False to 0.0.
bool to str str(True) 'True' Converts boolean to string.
bool to complex complex(True) (1+0j) Converts boolean to complex.
bool to list list([True]) [True] Converts boolean wrapped in a list.
bool to tuple tuple([True]) (True,) Converts boolean wrapped in a tuple.
bool to set set([True]) {True} Converts boolean wrapped in a set.
bool to dict dict([(True, 'a')]) {True: 'a'} Converts boolean key wrapped in a dict.

5. NoneType (None) Conversions

Type Conversion Syntax Result


str str(None) 'None'
int int(None) TypeError
float float(None) TypeError
bool bool(None) False
list list(None) TypeError
tuple tuple(None) TypeError
set set(None) TypeError
dict dict(None) TypeError
Operators
• Operators are special symbols in Python that carry out arithmetic or
logical computation
• The value that the operator operates on is called the operand
Operator Precedence and Associativity
Operator Description Precedence Associativity
() Parentheses Highest Left-to-right
** Exponentiation (power) 1st Right-to-left
+x, -x, ~x Unary plus, Unary minus, Bitwise NOT 2nd Right-to-left
Multiplication, Division, Floor
*, /, //, % 3rd Left-to-right
Division, Modulus
+, - Addition, Subtraction 4th Left-to-right
<<, >> Bitwise left shift, Bitwise right shift 5th Left-to-right
& Bitwise AND 6th Left-to-right
^ Bitwise XOR 7th Left-to-right
| Bitwise OR 8th Left-to-right
==, !=, >, <, >=, <= Equality, Inequality, Comparison 9th Left-to-right
not Logical NOT 10th Right-to-left
and Logical AND 11th Left-to-right
or Logical OR 12th Left-to-right
if-else Conditional expression 13th Right-to-left
=, +=, -=, *=, /=, //=,
Assignment, Augmented assignment 14th Right-to-left
%=**, **=
: Slicing (used in list/tuple slicing) 15th Left-to-right
, Tuple and list element separator 16th Left-to-right

Operator Type Operator Description Example Result


Arithmetic + Addition 5 + 3 8
- Subtraction 5 - 3 2
* Multiplication 5 * 3 15
/ Division (returns float) 5 / 3 1.6667

// Floor Division (integer 5 // 3 1


part)
% Modulus (remainder) 5 % 3 2
** Exponentiation 5 ** 3 125
Comparison == Equal to 5 == 3 False
!= Not equal to 5 != 3 True
> Greater than 5 > 3 True
< Less than 5 < 3 False
>= Greater than or equal to 5 >= 3 True
<= Less than or equal to 5 <= 3 False
Operator Type Operator Description Example Result
Logical and Logical AND (5 > 3) and (8 > 5) True
or Logical OR (5 > 3) or (8 < 5) True
not Logical NOT not (5 > 3) False
Assignment = Assignment x = 5 x is 5
+= Add and assign x += 3 x is 8
-= Subtract and assign x -= 3 x is 2
*= Multiply and assign x *= 3 x is 15
/= Divide and assign x /= 3 x is 1.6667
%= Modulus and assign x %= 3 x is 2
**= Exponentiate and assign x **= 3 x is 125
Bitwise & Bitwise AND 5 & 3 1
| Bitwise OR x|y 14
^ Bitwise XOR 5 ^ 3 6
~ Bitwise NOT ~5 -6
<< Left shift 5 << 1 10
>> Right shift 5 >> 1 2

in Checks membership in a 5 in [1, 2, 3, 5] True


Membership
sequence
not in Checks non-membership in 5 not in [1, 2, 3] True
a sequence
Checks if two variables True if x and y are
Identity is x is y
point to the same object the same object
True if x and y are
is not Checks if two variables x is not y
point to different objects different objects

F-strings or formatted string literals

Basic Syntax: To create an f-string, prefix the string with f or F


name = "Alice"
age = 30
greeting = f"Hello, {name}. You are {age} years old."
print(greeting) # Output: Hello, Alice. You are 30 years old.

• You can include various expressions inside the curly braces {}:
a = 5
b = 10
result = f"The sum of {a} and {b} is {a + b}."
print(result) # Output: The sum of 5 and 10 is 15.

• Fixed Decimal Places


pi = 3.14159
formatted_pi = f"Value of pi: {pi:.2f}"
print(formatted_pi) # Output: Value of pi: 3.14

• Commas as Thousands Separators


large_number = 1234567
formatted_number = f"Large number: {large_number:,}"
print(formatted_number) # Output: Large number: 1,234,567
• Percentage
success_rate = 0.879
formatted_rate = f"Success rate: {success_rate:.1%}"
print(formatted_rate) # Output: Success rate: 87.9%

• Left-Align
name = "Alice"
formatted_name = f"{name:<10}" # 10-character wide, left-aligned
print(f"'{formatted_name}'") # Output: 'Alice '

• Right-Align
name = "Alice"
formatted_name = f"{name:>10}" # 10-character wide, right-aligned
print(f"'{formatted_name}'") # Output: ' Alice'

• Center
name = "Alice"
formatted_name = f"{name:^10}" # 10-character wide, centered
print(f"'{formatted_name}'") # Output: ' Alice '

• Formatting Date

from datetime import datetime


now = datetime.now()
formatted_date = f"Current date and time: {now:%Y-%m-%d %H:%M:%S}"
print(formatted_date) # Output: Current date and time: 2024-07-16 12:34:56

Using Expressions
a = 5
b = 10
c = 15
result = f"The average of {a}, {b}, and {c} is {(a + b + c) / 3:.2f}"
print(result) # Output: The average of 5, 10, and 15 is 10.00

Nested f-strings
name = "Alice"
age = 30
info = f"Name: {name}, Age: {age}"
formatted_info = f"User Info: {info}"
print(formatted_info) # Output: User Info: Name: Alice, Age: 30

Using Function Calls


def greet(name):
return f"Hello, {name}"
greeting = f"{greet('Alice')}, welcome to the system."
print(greeting) # Output: Hello, Alice, welcome to the system.

Custom Formatting with format()


name = "Alice" age = 30
message = "Name: {}, Age: {}".format(name, age)
print(message) # Output: Name: Alice, Age: 30
# Positional arguments
message = "First: {}, Second: {}".format('apple', 'banana')
print(message) # Output: First: apple, Second: banana

# Keyword arguments
message = "Name: {name}, Age: {age}".format(name="Alice", age=30)
print(message) # Output: Name: Alice, Age: 30

value = 123.456789
formatted = "Value: {:.2f}".format(value)
print(formatted) # Output: Value: 123.46

text = "Python"
formatted = "{:<10}".format(text) # 10-character wide, left-aligned
print(f"'{formatted}'") # Output: 'Python '

Escape Curly Braces


name = "Alice"
message = f"{{name}} is a placeholder. Actual name is {name}."
print(message) # Output: {name} is a placeholder. Actual name is Alice.

Multiline f-strings
name = "Alice"
age = 30
message = f"""
Hello, {name}!
You are {age} years old.
"""
print(message)
# Output:
# Hello, Alice!
# You are 30 years old.

Type()
It is a built-in function that returns the type of the specified object or creates new types dynamically
x = 42
print(type(x)) # Output: <class 'int'>

x = 3.14
print(type(x)) # Output: <class 'float'>

x = "Hello"
print(type(x)) # Output: <class 'str'>

x = [1, 2, 3]
print(type(x)) # Output: <class 'list'>

x = (1, 2, 3)
print(type(x)) # Output: <class 'tuple'>

x = {'key': 'value'}
print(type(x)) # Output: <class 'dict'>
x = {1, 2, 3}
print(type(x)) # Output: <class 'set'>

x = True
print(type(x)) # Output: <class 'bool'>

print(type(None)) # Output: <class 'NoneType'>

Using type() for Type Checking


def is_integer(value):
return type(value) == int

print(is_integer(10)) # Output: True


print(is_integer(10.5)) # Output: False

Using type() for Type Creation


1. Creating New Types Dynamically: You can use type() to create new types dynamically.
This involves specifying the name, base classes, and attributes for the new type:
# Create a new type
MyClass = type('MyClass', (object,), {'attribute': 42})

# Create an instance of MyClass


instance = MyClass()

print(type(instance)) # Output: <class '__main__.MyClass'>


print(instance.attribute) # Output: 42

2. Using type() to Create a Class: type() can be used to create a new class dynamically:
# Define a class dynamically
MyClass = type('MyClass', (object,), {'greet': lambda self: 'Hello'})

obj = MyClass()
print(obj.greet()) # Output: Hello

Functions

Purpose of Functions
• Modularity: Functions allow you to break a program into smaller, manageable pieces, each
performing a specific task.
• Reusability: Once defined, a function can be reused throughout your code, avoiding
duplication.
• Organization: Functions help organize code logically, making it easier to understand and
maintain.
• function uses c calling conventions

Syntax
def function_name(parameters):
"""
docstring
"""
# statement(s)
return value

function_name() # function call

• def: Keyword used to define a function.


• function_name: The name of the function.
• Parameters (optional): comma-separated list of inputs that the function can accept.
• docstring: (Optional) A string literal that describes the function’s purpose. It’s enclosed
in triple quotes and can be accessed using the .__doc__ attribute.
• statement(s): The block of code that performs the task of the function. This block must
be indented.
• return: (Optional): Keyword used to return a valueThe value that the function returns to
the caller. If omitted, the function returns None.

• pass: do not do anything, pass the control to the next line, used to create empty
function/class

Examples
1. Empty function
def empty_function():
pass
2. Parameterless Function
def greet():
print("Hello, World!")
greet() # Output: Hello, World!

3. Parameterized Function
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # Output: Hello, Alice!

4. Function with Return Value


def add(a, b):
return a + b
result = add(5, 3)
print(result) # Output: 8

5. Function with Default Parameters


def greet(name="World"):
print(f"Hello, {name}!")
greet() # Output: Hello, World!
greet("Alice") # Output: Hello, Alice!

6. Function with Docstring


def multiply(x, y):
"""
Multiply two numbers and return the result.
"""
return x * y
print(multiply.__doc__) # Output: Multiply two numbers and return the
result.

7. Function with Multiple Return Values


def arithmetic_operations(a, b):
return a + b, a - b, a * b, a / b
add, subtract, multiply, divide = arithmetic_operations(10, 5)
print(add, subtract, multiply, divide) # Output: 15 5 50 2.0

8. Nested Function

• the inner function can be called only within the function in which it is declared

• inner function can access all the members of outer function4

• outer function can not access any members of inner function

• outer function can have as many inner function as required

• outer function can have a hierarchy of inner functions

def outer():
print(“inside outer”)
def inner():
print(”inside inner”)
inner()
outer()
inner() # error as it has local scope
9. Lambda / Anonymous Functions: Lambda functions are small anonymous functions
defined using the lambda keyword. They can take any number of arguments but have only
one expression.
Syntax lambda arguments: expression
Characteristics
• It can only contain expressions and can’t include statements in its body
• It is written as a single line of execution
• It does not support type annotations. It can be immediately invoked
• Lambda must accept at least one parameter
• the body statement must return a value
square = lambda x: x * x
print(square(5)) # Output: 25

Scope of Variables
Scope of a variable is the portion of a program where the variable is recognized
The lifetime of a variable is the period throughout which the variable exists in the memory
• Local Scope: Parameters and variables defined inside a function are not visible from outside
the function. Hence, they have a local scope.
• The lifetime of variables inside a function is as long as the function executes
• They are destroyed once we return from the function. Hence, a function does not remember
the value of a variable from its previous calls.
def foo():
local_var = "local"
foo()
print(local_var) # error

• Global Scope: Variables defined outside of all functions are global and can be accessed
from within functions, but they must be declared as global if modified inside the function.
• Rules of global Keyword
• When we create a variable inside a function, it is local by default
• When we define a variable outside of a function, it is global by default. You don't
have to use global keyword
• We use global keyword to read and write a global variable inside a function
• Use of global keyword outside a function has no effect
g_var = "global"
def foo():
print(g_var)
foo()

x = 10 # Global variable
def modify():
global x
x = 20
modify()
print(x) # Output: 20

Function Types
1. Built-in functions
• Functions that readily come with Python are called built-in functions. E.g., str(), int(), float()
• If we use functions written by others in the form of library, it can be termed as library
functions
2. User defined functions
• Functions that we define ourselves to do certain specific task are referred as user-defined
functions
• Programmers working on large project can divide the workload by making different
functions
Function parameters
1. Positional parameters: do not have parameter name whlie making the function name the values
will get assigned to the parameters from left to right
def function_3(num1, num2, num3):
print(f"num1 = {num1}, num2 = {num2}
function_3(10, 20, 30) # num1 = 10, num2 = 20, num3 = 30
2. Named parameters: the function call will contain the parameter name along with the parameter
value
def function_3(num1, num2, num3):
print(f"num1 = {num1}, num2 = {num2}
function_3(num3=30, num2=20, num1=10) # num1 = 10, num2 = 20, num3 = 30
3. Optional parameters: a function can set a default value for a parameter caller does not need to
pass a value for such parameters. The parameter having default value becomes optional (caller may
or may not pass the value forsuch parameter)
def function_1(p1, p2=50): # p2 has a default value = 50
print(f"{p1}, {2}")
function_1(10) # p1 = 10, p2 = 50
function_1(10, 20) # p1 = 10, p2 = 20
Variable length argument function
• when the function gets called
◦ the positional parameters get collected in a tuple (args)
◦ the named parameters get collected in a dictionary (kwargs)
def va_function(*args, **kwargs):
print(f"args = {args}, type = {type(args)}")
print(f"kwargs = {kwargs}, type = {type(kwargs)}")
va_function(10, 20) # args = (10, 20)
va_function(p1=10, p2=20) # kwargs = {'p1': 10, 'p2': 20}
va_function(10, 20, p1=30, p2=40) # args = (10, 20), kwargs = {'p1': 30, 'p2': 40}

def add(*args): # args will collect all the arguments in a tuple


print(f"args = {args}, type = {type(args)}")
result = ""
for value in args:
result += value
print(f"addition = {result}")

Function alias
Another name given to an existing function. Similar to function pointer in C
def function_2():
print("inside function_2")
my_function = function_2 # function alias
function_2() # inside function_2
my_function() # inside function_2

Collections in Python
Python provides several built-in collection types that allow you to store, organize, and manipulate
groups of related data. Each collection type has its unique properties and use cases.

1. Lists
- ordered collection of similar to dis-similar values
- to create a list use []
- the values in list are not allocated contiguously
- internally the list is implemented as linked list
- is mutable collection
numbers = [10, 20, 30, 40, 50]
print(f"length of numbers = {len(numbers)}") # get the size or length of numbers

# iterate over the list


# for <temp variable> in <collection>:
for number in numbers:
print(f"number = {number}")

numbers2 = list() # empty list


numbers1 = [] # empty list

Return
Method Syntax Parameters Description Example
Value
lst = [1, 2];
Adds an item to the end lst.append(3);
append() list.append(item) item: Element to add None
of the list. print(lst)
Extends the list by lst = [1, 2];
iterable: List or
extend() list.extend(iterable) None appending elements lst.extend([3, 4]);
iterable print(lst)
from an iterable.
Inserts an item at a lst = [1, 2];
list.insert(index, index: Position,
insert() None specified position in the lst.insert(1, 1.5);
item) item: Element
list. print(lst)
Removes the first lst = [1, 2, 3];
item: Element to
remove() list.remove(item) None occurrence of an item lst.remove(2);
remove print(lst)
from the list.
Removes and returns
the item at the specified
index: Position Element at lst = [1, 2, 3];
pop() list.pop([index]) position. If no index is
(optional) index lst.pop(); print(lst)
specified, it removes
and returns the last item.
Removes all items from lst = [1, 2, 3];
clear() list.clear() None None
the list. lst.clear(); print(lst)
item: Element to find,
Returns the index of the lst = [1, 2, 3];
list.index(item, start: Start position Index of
index() first occurrence of an
start, end) (optional), end: End item print(lst.index(2))
item.
position (optional)
Returns the number of lst = [1, 2, 2, 3];
item: Element to Count of
count() list.count(item) times an item appears in print(lst.count(2))
count item
the list.
key: Function to
list.sort(key=None, Sorts the items of the lst = [3, 1, 2];
sort() customize sort None
reverse=False) list in place (default is lst.sort(); print(lst)
(optional), reverse:
ascending order).
Sort order (optional)
lst = [1, 2, 3];
reverse() list.reverse() None Reverses the elements lst.reverse();
None
of the list in place. print(lst)
lst = [1, 2, 3]; new_lst
copy() list.copy() Shallow copy Returns a shallow copy = lst.copy();
None
of list of the list. print(new_lst)

len() len(list) Returns the number of lst = [1, 2, 3];


None Length of list print(len(lst))
items in the list.
Creating List

1. Using Square Brackets


my_list = [1, 2, 3, 4, 5]

2. Using the list() Constructor


my_list = list((1, 2, 3, 4, 5)) # From a tuple
my_list = list("hello") # From a string
my_list = list(range(5)) # From a range

3. Using List Comprehension


my_list = [x**2 for x in range(5)] #Squares of numbers 0 to 4
my_list = [x for x in range(5) if x % 2 == 0] # Even numbers 0-4

4. Using the * Operator


my_list = [0] * 5 # Creates a list [0, 0, 0, 0, 0]

5. Using append() Method in a Loop


my_list = []
for i in range(5):
my_list.append(i)

6. Using List Multiplication and Addition


my_list = [1] + [2, 3, 4] # [1, 2, 3, 4]
my_list = [0] * 3 + [1, 2] # [0, 0, 0, 1, 2]

7. From Existing Data Structures


tuple_data = (1, 2, 3)
my_list = list(tuple_data) # Convert tuple to list

set_data = {4, 5, 6}
my_list = list(set_data) # Convert set to list

8. Using extend() Method


my_list = []
my_list.extend([1, 2, 3])

Accessing elements of List


1. Positive Indexing: Access elements using positive integers, starting from 0.
my_list = [10, 20, 30, 40, 50]
element = my_list[2] # Accesses the element at index 2 (30)

2. Negative Indexing: Access elements from the end of the list using negative integers, starting
from -1.
element = my_list[-1] # Accesses the last element (50)
element = my_list[-2] # Accesses the second-to-last element (40)

3. Slicing: Access a range of elements using a slice, which includes a start index, end index, and
optionally a step.
sub_list = my_list[1:4] #Accesses elements from index 1 to 3 ([20, 30, 40])
sub_list = my_list[:3] #Accesses elements from the start to index 2 ([10, 20, 30])
sub_list = my_list[2:] #Accesses elements from index 2 to the end ([30, 40, 50])

print(f"reversed collection : {numbers[::-1]}") # return reversed collection

4. Step in Slicing
sub_list = my_list[::2] # Accesses every second element ([10, 30, 50])

5. Using enumerate() for Index and Value


for index, value in enumerate(my_list):
print(f"Index: {index}, Value: {value}")

6. Using List Methods


element = my_list.pop(2) # Removes and returns the element at index 2 (30)
index = my_list.index(40) # Finds the index of the element 40 (3)

Iterating Over Lists


# Iterating with a for loop
for item in numbers:
print(item)

# List with enumeration


for index, item in enumerate(numbers):
print(index, item)

List Operations
# Concatenation
lst1 = [1, 2]
lst2 = [3, 4]
combined = lst1 + lst2 # Output: [1, 2, 3, 4]

# Repetition
repeated = lst1 * 3 # Output: [1, 2, 1, 2, 1, 2]

# Membership
is_member = 2 in lst1 # Output: True

Else Statements
1. In an if-elif-else Chain
The else block runs if none of the if or elif conditions are True.
x = 10
if x > 20:
print("x is greater than 20")
elif x > 5:
print("x is greater than 5 but less than or equal to 20")
else:
print("x is 5 or less")

2. In a while Loop with else and break


The else block runs when the loop finishes normally (i.e., it was not terminated by a break
statement).

i = 0
while i < 5:
print(i)
if i == 3:
break
i += 1
else:
print("Loop completed without break") # This will not be printed

3. In a for Loop with else and break


The else block runs when the loop finishes normally (i.e., it was not terminated by a break
statement).
for i in range(5):
print(i)
if i == 3:
break
else:
print("Loop completed without break") # This will not be printed

4. In a try-except-finally Block
The finally block always runs, regardless of whether an exception occurred. However, you can
use else to specify code that runs only if no exceptions are raised.
try:
result = 10 / 2
except ZeroDivisionError:
print("You can't divide by zero!")
else:
print("Division successful:", result)
finally:
print("This block always runs")

2. Tuples
- ordered collection of similar and dissimilar values
- tuple is immutable (once created, it can not be changed)
- () is used to create a tuple

1. Creating Tuples
• Basic Tuple Creation:
my_tuple = (1, 2, 3)

• Single Element Tuple: Include a trailing comma.


• the following are not tuples, rather they are simple int and str variables
# numbers_tuple = (10)

# countries_tuple = ("india")
single_element_tuple = (1,)

• Empty Tuple:
empty_tuple = ()

• Tuple from Multiple Values:


tuple_from_values = 1, 2, 3

• Using tuple() Constructor:


tuple_from_list = tuple([1, 2, 3])
tuple_from_string = tuple('hello') # ('h', 'e', 'l', 'l', 'o')

2. Accessing Tuple Elements


• Postive Indexing:
my_tuple = (10, 20, 30)
print(my_tuple[0]) # 10
print(my_tuple[1]) # 20

• Negative Indexing:
print(my_tuple[-1]) # 30 (last element)
print(my_tuple[-2]) # 20 (second-to-last element)

• Slicing:
print(my_tuple[1:3]) # (20, 30)
print(my_tuple[:2]) # (10, 20)
print(my_tuple[1:]) # (20, 30)

3. Tuple Operations
• Concatenation:
tuple1 = (1, 2)
tuple2 = (3, 4)
concatenated_tuple = tuple1 + tuple2 # (1, 2, 3, 4)

• Repetition:
repeated_tuple = (1, 2) * 3 # (1, 2, 1, 2, 1, 2)

• Membership Testing:
print(2 in (1, 2, 3)) # True
print(4 in (1, 2, 3)) # False

• Length:
length = len((1, 2, 3)) # 3

4. Immutability
• Tuples are immutable: You cannot change, add, or remove elements once a tuple is created.
my_tuple = (1, 2, 3)
# my_tuple[1] = 4 # This will raise a TypeError

• Modifying Mutable Elements Inside Tuples: If a tuple contains mutable objects (e.g.,
lists), you can modify the mutable objects, but you cannot reassign the tuple itself.
tuple_with_list = ([1, 2], [3, 4])
tuple_with_list[0].append(3) # ([1, 2, 3], [3, 4])

5. Tuple Packing and Unpacking


• Packing: Assign multiple values to a single tuple.
packed_tuple = 1, 2, 3

• Unpacking: Extract values from a tuple into variables.


a, b, c = (1, 2, 3)
print(a) # 1
print(b) # 2
print(c) # 3

• Extended Unpacking: Capture multiple values into a list.


a, *rest = (1, 2, 3, 4)
print(a) # 1
print(rest) # [2, 3, 4]

• tuple packing AND unpacking

n1, n2 = 10, 20

n1, n2 = n2, n1 # Swap values

6. Tuples and Functions


• Returning Multiple Values from Functions:
def get_coordinates():
return (10, 20)
x, y = get_coordinates()
print(x) # 10
print(y) # 20

7. Tuple Methods

Method Description Syntax Parameters Returns Example


Counts the
my_tuple = (1, 2, 2, 3,2)
number of value (the value to
count() tuple.count(value) int count_2 =my_tuple.count(2)
occurrences of a count)
print(count_of_2) # 3
value.
value (the value to
Finds the index
find), start (optional my_tuple = (1, 2, 3, 2, 4)
of the first tuple.index(value, start,
index() start index), end int index_2 = my_tuple.index(2)
occurrence of a end)
(optional end print(index_of_2) # 1
value.
index)

8. Tuple Comprehension
Unlike lists, tuples do not support list comprehensions. However, you can use a generator
expression and convert it to a tuple.
tuple_comprehension = tuple(x**2 for x in range(5)) # (0, 1, 4, 9, 16)

9. Applications of Tuples
• Dictionary Keys: Tuples can be used as keys in dictionaries because they are immutable
and hashable.
my_dict = {('a', 'b'): 1, ('c', 'd'): 2}

multi-dimensional collection (collection of collections)


# - list of lists
numbers = [
[10, 20], # 0: [0, 0] [0, 1]
[30, 40], # 1: [1, 0] [1, 1]
[50, 60] # 2: [2, 0] [2, 1]
]
for values in numbers:
print(values) # for rows
for value in values:
print(f"value = {value}") # for columns
# - list of tuples
def function5():
cars = [("mahindra", "xuv", 20),
("tata", "nano", 2.5) ]
for company, model, price in cars: # tuple unpacking
print(f"company = {company}")
print(f"model = {model}")
print(f"price = {price}")
print("-" * 80)
# - tuple of tuples
# - tuple of lists

3. Set
- collection of unique values
- mutable collection
- unordered collection: does not honor the insertion order
- uses hashing behind the scene
- indexing does not work with set

1.. Creating Sets


• Basic Set Creation:
my_set = {1, 2, 3}

• Empty Set: Note that an empty set must be created using the set() constructor; {}
creates an empty dictionary.
empty_set = set()

• Set from List or Other Iterable:


my_set = set([1, 2, 3, 2, 1]) # {1, 2, 3}

• Set from String:


char_set = set("hello") # {'h', 'e', 'l', 'o'}

3. Basic Set Operations


• Checking Membership:
1 in my_set # True
• Set Length:
len(my_set) # Number of elements in the set

4. Set Methods
Method Description Syntax Parameters Returns Example
my_set = {1, 2, 3}
Adds an element element (the
add() set.add(element) None my_set.add(4)
to the set. element to add)
print(my_set) # {1, 2, 3, 4}
Removes a
Remove() specified element. element (the my_set = {1, 2, 3}
(raises KeyError if set.remove(element) element to None my_set.remove(2)
element not found) remove) print(my_set) # {1, 3}

Removes a
element (the my_set = {1, 2, 3}
specified element
discard() set.discard(element) element to None my_set.discard(2)
without raising
discard) print(my_set) # {1, 3}
an error.
my_set = {1, 2, 3}
Removes and
element = my_set.pop()
pop() returns an set.pop() - element
print(element)
arbitrary element.
print(my_set)
Removes all my_set = {1, 2, 3}
clear() elements from the set.clear() - None my_set.clear()
set. print(my_set) # set()
my_set = {1, 2, 3}
Returns a shallow
copy() set.copy() - set new_set = my_set.copy()
copy of the set.
print(new_set) # {1, 2, 3}

5. Set Operations
• Union: Combines elements from both sets.
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union_set = set1 | set2 # {1, 2, 3, 4, 5}

# or set1.union(set2)

• Intersection: Returns elements common to both sets.


intersection_set = set1 & set2 # {3}

# or set1.intersection(set2)

• Difference: Returns elements in the first set but not in the second set.
difference_set = set1 - set2 # {1, 2}

# or set1.difference(set2)

• Symmetric Difference: Returns elements in either set but not in both.


symmetric_difference_set = set1 ^ set2 # {1, 2, 4, 5}

• Subset: Checks if all elements of one set are in another.


subset_check = {1, 2} <= set1 # True
• Superset: Checks if all elements of another set are in the set.
superset_check = set1 >= {1, 2} # True

6. Set Comprehension
squared_set = {x**2 for x in range(5)} # {0, 1, 4, 9, 16}

frozenset

- immutable collection of unique values

def function1():
s1 = frozenset([10, 20, 30, 40, 50, 10, 20, 30, 40, 50])
print(f"s1 = {s1}, type = {type(s1)}") # type = <class 'frozenset'>
# can not be updated
# s1.add(10)
function1()

4. Dictionary
- unordered collection of key-value pairs
- mutable
- key:
- must be of data type string
- must be unique
- case sensitive
- value: can be of any data type

1. Creating Dictionaries
• Basic Dictionary Creation:
my_dict = {'key1': 'value1', 'key2': 'value2'}

# the last value will be the final value


# this code doest not produce any error
person = { "name": "person2",
"name": "person3",
"name": "person1",
"age": 30}

• Using the dict() Constructor:


my_dict = dict(key1='value1', key2='value2')

• From a List of Tuples:


pairs = [('key1', 'value1'), ('key2', 'value2')]
my_dict = dict(pairs)

• From a List of Lists:


pairs = [['key1', 'value1'], ['key2', 'value2']]
my_dict = dict(pairs)

2. Accessing Values
• By Key: if the key does not exist, the application will raise an exception KeyError
value = my_dict['key1'] # 'value1'

• Using get() Method: if the key does not exist, you will get None as value
value = my_dict.get('key1') # 'value1'
# You can also provide a default value if the key is not found
value = my_dict.get('key3', 'default_value') # 'default_value'

3. Adding and Modifying Entries


my_dict['key3'] = 'value3' # if key doesn’t exist, the value along with key
# will be added
my_dict['key1'] = 'new_value1' # if the key exists, the value gets updated

4. Dictionary Methods

Method Description Syntax Parameters Returns Example


Returns a
shallow copy copy_dict = my_dict.copy()
copy() dict.copy() - dict
of the print(copy_dict)
dictionary.
Creates a new
keys = ['key1', 'key2']
dictionary iterable (keys),
dict.fromkeys(iterable, new_dict =
fromkeys() from keys with value dict
value) dict.fromkeys(keys, 'default')
a specified (optional)
print(new_dict)
value.
Returns the value = my_dict.get('key1',
key, default value or
get() value for the dict.get(key, default) 'default')
(optional) default
given key. print(value)
Returns a view
items = my_dict.items()
items() object of key- dict.items() - view
print(items)
value pairs.
Returns a view keys = my_dict.keys()
keys() dict.keys() - view
object of keys. print(keys)
Removes the
value = my_dict.pop('key1',
specified key key, default
pop() dict.pop(key, default) value 'default')
and returns its (optional)
print(value)
value.
key, value =
Removes and
my_dict.popitem()
popitem() returns the last dict.popitem() - tuple
key-value pair.
print(key, value)
Returns the
value of the value =
key. If the key my_dict.setdefault('key1',
key, default
setdefault() does not exist, dict.setdefault(key, default) value 'default')
(optional)
inserts it with a
specified print(value)
value.
Method Description Syntax Parameters Returns Example
Updates the
dictionary with
my_dict.update({'key4':
key-value pairs other (dict or
update() dict.update([other]) None 'value4'})
from another iterable)
print(my_dict)
dictionary or
iterable.
Returns a view
values = my_dict.values()
values() object of dict.values() - view
print(values)
values.

5. Iterating Over Dictionaries


• Iterate Over Keys:
for key in my_dict:
print(key, my_dict[key])

cars = [{"model": "triber", "company": "renault", "price": 10},


{"model": "nano", "company": "tata", "price": 2.5},
{"model": "X5", "company": "BMW", "price": 45}]
for car in cars:
for key in car:
print(f"{key} = {car[key]}")
print()
• Iterate Over Values:
for value in my_dict.values():
print(value)

• Iterate Over Key-Value Pairs:


for key, value in my_dict.items():
print(key, value)

6. Dictionary Comprehension
squares = {x: x**2 for x in range(6)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

7. Use Cases
• Data Mapping: Useful for mapping relationships, such as names to phone numbers.
• Counting Occurrences: Count occurrences of items with keys.
• Configuration Settings: Store configuration settings where keys are setting names.

8. Dictionary Operations
• Checking if Key Exists:
if 'key1' in my_dict:
print("Key exists")
Functional programming
It is a programming paradigm that treats computation as the evaluation of mathematical functions
and avoids changing state and mutable data.
1. Basic Concepts of Functional Programming
• First-Class Functions: Functions are treated as first-class citizens, meaning they can be
assigned to variables, passed as arguments, and returned from other functions.
• Pure Functions: Functions that have no side effects and return the same output given the
same input.
• Higher-Order Functions: Functions that take other functions as arguments or return
functions as their results.
• Immutable Data: Data that cannot be modified after it is created.
• Recursion: Functions that call themselves as part of their execution.

2. First-Class Functions
• Assigning Functions to Variables:
def add(a, b):
return a + b

sum_function = add
print(sum_function(2, 3)) # Output: 5

• Passing Functions as Arguments:


def apply_function(func, a, b):
return func(a, b)

result = apply_function(add, 2, 3)
print(result) # Output: 5

• Returning Functions from Functions:


def outer_function(x):
def inner_function(y):
return x + y
return inner_function
add_five = outer_function(5)
print(add_five(3)) # Output: 8

3. Higher-Order Functions
• Map: Applies a function to all items in an input list.
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))
print(squared) # Output: [1, 4, 9, 16]

• Filter: Constructs a list from those elements of the input list for which the function returns
true.
numbers = [1, 2, 3, 4]
even = list(filter(lambda x: x % 2 == 0, numbers))
print(even) # Output: [2, 4]

• Reduce: Applies a rolling computation to sequential pairs of values in a list (from


functools).
from functools import reduce
numbers = [1, 2, 3, 4]
sum = reduce(lambda x, y: x + y, numbers)
print(sum) # Output: 10

4. Recursion
• Recursive Functions: Functions that call themselves.
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)

print(factorial(5)) # Output: 120

list of dictionary

cars = [ {"model": "triber", "company": "renault", "price": 10},


{"model": "kwid", "company": "renault", "price": 7}]
# find every car's company
extract_info = lambda car: car["company"]
companies = list(map(extract_info, cars))
# or companies = [car['companies'] for car in cars]

# find the affordable cars (price <= 20)


is_affordable = lambda car: car['price'] <= 20
affordable_cars = list(filter(is_affordable, cars))
# affordable_cars = [car for car in cars if car['price'] <= 20]

# find affordable car's model


# filter + map
extract_model = lambda car: car['model']
affordable_models = list(map(extract_model, affordable_cars))
print(affordable_models)
Class
- blueprint to create an object
- user defined data structure
- encapsulates
- data (attributes)
- member functions/beahvaior (methods): functions defined inside class
- convention
- the first character of the class name should be in upper case
- types
- depending on the body
- empty class
- concrete class
- built-in functions
- setattr(): used to add/set an attribute value
- getattr(): used to get value of an attribute
object (instance)
- memory allocated to store the class attributes
- every object must be identified by a unique address
- state: the value of every attribute at a give time
- instantiation: process of creating an object

object creation
- when an object gets created, two memory blocks will be allocated
- one for the object (to store the data)
- second one for the reference (used to refer the object)
- every object gets created on new memory location. Every object has a unique memory address

method
- function declared inside the class
- types
1. __init__ (Initializer): Initializes an instance of the class.
• gets called automatically for every object. must not be called explicitly
• called as a constructor in other languages
• types
• default: no parameter other than self (parameterless initializer)
class Person:
def __init__(self):
print("inside __init__")
• custom(parameterized initializer): with at least one parameter other than self

class MyClass:
def __init__(self, value):
self.value = value

2. __del__ (de-initializer): used to de-initialize the object called as a destructor in other languages

• gets called automatically/implicitly when an object is about to be destroyed, which is when


the object's reference count reaches zero and it is garbage collected.
class Mobile:
def __init__(self, model, price):
self.model = model
self.price = price

def print_info(self):
print(f"model = {self.model}")
print(f"price = {self.price}")

def __del__(self):
print("-- inside __del__ method --")

def is_affordable(self):
if self.price <= 20000:
print(f"{self.model} is affordable")
else:
print(f"{self.model} is NOT affordable")

m1 = Mobile("iphone", "apple", 100000, "8GB")


m1.print_info()
m1.is_affordable()

3. Getters (inspector)
4. Setters(mutator)

Purpose:

• Encapsulation: Protects internal data and prevents unauthorized access.


• Validation: Ensures data meets certain criteria before modification.
• Abstraction: Simplifies data handling and presents a clean interface.
• Getters: Methods to retrieve private or protected attributes.
• Setters: Methods to update private or protected attributes with optional validation.
class Person:

def get_age(self):
return self.__age

def set_age(self, age):


if age > 0:
self.__age = age
else:
raise ValueError("Age must be positive")

5. facilitator: adds facility in the class


class Person:
def __init__(self, name, age): # initializer
self.name = name
self.age = age
def can_vote(self): # facilitator
if self.age >= 18:
print("yes")
else:
print("no")
1. Empty Class Definition
class MyClass:
pass

obj = MyClass() # Creating an Instance

# anonymous object: which does not have any reference


MyClass()

# creates a new reference referring the old object


obj2 = obj

-getattr
The getattr function is used to retrieve the value of an attribute from an object. It takes three
arguments: getattr(object, name, default)
• object: The object from which the attribute is to be retrieved.
• name: A string representing the name of the attribute.
• default: An optional value to return if the attribute does not exist.
-setattr
The setattr function is used to set the value of an attribute on an object. It takes three
arguments: setattr(object, name, value)
• object: The object on which the attribute is to be set.
• name: A string representing the name of the attribute.
• value: The value to set for the attribute.
setattr(obj, "name", "Bob")
name = getattr(person, "name", “Unknown”)

class Mobile:
def print_info(self): # method
print(f"model = {getattr(self, 'model')}")
print(f"price = {getattr(self, 'price')}")
def set_attributes(self, model, price):
setattr(self, "model", model)
setattr(self, "price", price)

m = Mobile()
m.set_attributes("iphone", 100000)
m.print_info()
print(m.__dict__) # Output: {'model': 'iphone', 'price': 100000}

• You can use __dict__ to get a dictionary of all the attributes of an object.
# Modifying the __dict__ attribute
person.__dict__['name'] = "Bob"
person.__dict__['age'] = 40

2. Accessing Specifiers
Access Level Description Naming Convention Example Access
Public Accessible from outside the class No prefix object.attribute
Accessible only within the class, uses
Private name mangling- (python/internal) __prefix object._ClassName__attribute
feature, (compiler) version specific
Accessible from outside the class but
intended for internal use.
Protected _prefix object._attribute
Accessible in the same class and all of
its child classes
Internal Special methods for object-oriented
__prefix__suffix__ object.__method__
Methods features

3. Association (has-a)
represents associations of multiple classes
types
• aggregation
- also known as has-a relationship
- loose coupling / weak relationship: one entity can live without another entity
- e.g Student has-a address
• composition
- also known as composed-of / part-of
- tight coupling / strong relationship: one entity can not live without the other entity
- e.g. Car composed-of engine
class Employee:
def __init__(self, emp_id, name):
self.__emp_id = emp_id
self.__name = name
def print_employee_info(self):
print(f"id: {self.__emp_id}, name: {self.__name}")

class Company:
def __init__(self, name, address):
self.__name = name
self.__address = address
self.__employees = [] # Company has many Employee
def recruit(self, name, emp_id):
employee = Employee(emp_id, name)
self.__employees.append(employee)

def print_info(self):
print(f"name = {self.__name}")
print(f"address = {self.__address}")
print(f"-- employees --")
for employee in self.__employees:
employee.print_employee_info()

# create a company class object


company = Company("company 1", "pune")

# recruit employees
company.recruit("employee 1", 1)
company.recruit("employee 2", 2)

# print all the information


company.print_info()

4. Inheritance (is a relationship)


Inheritance is a fundamental concept in object-oriented programming where a newlass (called a
subclass or derived class) inherits attributes and methods from an existing class (called a parent
class, superclass, or base class). e.g. player is-a person
- One class is made up of another class
- the base class can be specified at the time of declaration with ()
- every subclass object will create an object of parent class within itself
NOTE
• Base class CAN NOT access any member(s) of derived class
• Derived class CAN access any (protected or public) member(s) of base class(es)
• Must initialize (call base class __init__) object of parent class in __init__ of derived class
The object Class:

- Python 3.x, every class is derived from the object class directly or indirectly

-object Class: Known as the root class or system class, it provides foundational methods like
memory management.
1. Single Inheritance: there is only one base class and only one derived class
class Person: # base class
def __init__(self, name):
self.name = name
def print_person_info(self):
print(f"name = {self.name}")
class Player(Person): # dervied class
def __init__(self, name, team):
Person.__init__(self, name)
self.team = teamclass Parent:
def parent_method(self):
print('This is a parent method')

-----------------------------------------------------------------
2. Multi-level Inheritance: there are multiple levels
- a level will have one base and one derived class
- a may have one direct and mulitple indirect base class(es)

class Person:
def __init__(self, name):
self._name = name
class Employee(Person):
def __init__(self, name, company):
Person.__init__(self, name)
self._company = company
class Manager(Employee):
def __init__(self, name, company, department):
Employee.__init__(self, name, company)
self._department = department

3. Multiple Inheritance: A class can inherit from multiple base classes.

class Faculty:
def __init__(self, name, subject):
self._name = name
self._subject = subject
class LabAssistant:
def __init__(self, name, lab):
self._name = name
self._lab = lab
class FacultyLabAssistant(Faculty, LabAssistant):
def __init__(self, name, subject, lab):
Faculty.__init__(self, name, subject)
LabAssistant.__init__(self, name, lab)

-------------------------------------------------------------------------------

4. Hybrid Inheritance: combination of any two or more inheritance

5. Polymorphism
- multiple forms of one thing
- types
- method overriding (run-time or dynamic polymorphism)
- Redefining a method in the child class that is already defined in the parent class.
- the method gets called from type of object
- compile-time polymorphism : NOT SUPPORTED n Python
- also known as function overloading
- multiple functions with same name but
- different number of parameters
- different type of parameters
- different order of parameters

Method Overriding
class Parent:
def show(self):
print('Parent method')

class Child(Parent):
def show(self):
print('Child method')

obj = Child()
obj.show() # Output: Child method

• super() Function: Call a method from the parent class.


class Parent:
def show(self):
print('Parent method')

class Child(Parent):
def show(self):
super().show()
print('Child method')

obj = Child()
obj.show()
# Output:
# Parent method
# Child method

• __str__: Returns a string representation of the object.

• ....print(), str() calls .__str__ of object


• __str__ is overrides object class __str__() method

class MyClass:
def __init__(self, value):
self.value = value
def __str__(self):
return f'MyClass with value {self.value}'

obj = MyClass(10)
print(obj) # Output: MyClass with value 10

Operation Overloading
- provide different meaning to existing operators
magical methods
- mathematical operators (binary operator)
__add__: for addition
__sub__: for subtraction
__mul__: for multiplication
__truediv__: for true division (produces float result)
__floordiv__: for floor division (produces int result)
__mod__: for modulus
__pow__: for raised to (power) operation
- comparison operators (binary operator)
__gt__: for >
__lt__: for <
__ge__: for >=
__le__: for <=
__eq__: for ==
__ne__: for !=
- __getitem__: Indexing ( [] )
- __contains__: Membership testing (in)
class MyNumber:
def __init__(self, number: int):
self.__number = number
def __add__(self, other):
return self.__number + other.__number
def __pow__(self, power, modulo=None):
result = self.__number ** power
return MyNumber(result)

class Person:
def __init__(self, name, age):
self.__name = name
self.__age = age
def __gt__(self, other):
return self.__age > other.__age

p1, p2 = Person("person1", 20), Person("person2", 35)


print(f"p1 > p2 = {p1 > p2}")

6. Method Resolution Order (MRO)


• MRO: Determines the order in which base classes are searched when executing a method.
You can view the MRO using the mro() method or the __mro__ attribute.
class A:
pass

class B(A):
pass

class C(A):
pass

class D(B, C):


pass

print(D.mro())
print(D.__mro__)

# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class


'__main__.A'>, <class 'object'>)
7. Special Methods (Magic Methods or Dunder Methods)
• __init__ (Initializer): Initializes an instance of the class.
• gets called automatically for every object. must not be called explicitly
• called as a constructor in other languages
• types
• default: no parameter other than self
• custom: with at least one parameter other than self
class MyClass:
def __init__(self, value):
self.value = value

• __del__ (de-initializer): used to de-initialize the object called as a destructor in


other languages
• called when an object is about to be destroyed, which is when the object's reference count
reaches zero and it is garbage collected.
class Mobile:
def __init__(self, model, price):
self.model = model
self.price = price

def print_info(self):
print(f"model = {self.model}")
print(f"price = {self.price}")

def __del__(self):
print("-- inside __del__ method --")

def is_affordable(self):
if self.price <= 20000:
print(f"{self.model} is affordable")
else:
print(f"{self.model} is NOT affordable")

m1 = Mobile("iphone", "apple", 100000, "8GB")


m1.print_info()
m1.is_affordable()

• __len__: Returns the length of the object.


python
Copy code
class MyClass:
def __init__(self, value):
self.value = value

def __len__(self):
return len(self.value)

obj = MyClass([1, 2, 3])


print(len(obj)) # Output: 3

• __getitem__: Allows indexing.


python
Copy code
class MyClass:
def __init__(self, value):
self.value = value

def __getitem__(self, index):


return self.value[index]

obj = MyClass([1, 2, 3])


print(obj[1]) # Output: 2

8. Encapsulation
• Private Attributes: Indicated by prefixing the attribute name with double underscores.
python
Copy code
class MyClass:
def __init__(self, value):
self.__value = value

def get_value(self):
return self.__value

obj = MyClass(10)
print(obj.get_value()) # Output: 10
# print(obj.__value) # Raises AttributeError

9. Polymorphism
• Method Polymorphism: Methods in different classes having the same name.
python
Copy code
class Cat:
def sound(self):
return 'Meow'

class Dog:
def sound(self):
return 'Bark'

def make_sound(animal):
print(animal.sound())

cat = Cat()
dog = Dog()

make_sound(cat) # Output: Meow


make_sound(dog) # Output: Bark

11. Abstract Base Classes (ABCs)


• Abstract Classes: Defined using the abc module and cannot be instantiated. They can have
abstract methods that must be implemented by subclasses.
python
Copy code
from abc import ABC, abstractmethod

class Animal(ABC):
@abstractmethod
def sound(self):
pass

class Cat(Animal):
def sound(self):
return 'Meow'

cat = Cat()
print(cat.sound()) # Output: Meow

Exception Handling in Python


- Error
- when error occurs the application crashes
- errors can not be handled
- e.g. bad sector, not enough memory etc.

Key Concepts
1. Exception: An event that disrupts the normal flow of the program. Examples include
division by zero, accessing a variable that doesn't exist, etc.
2. Exception Handling: The process of responding to exceptions when they occur during
program execution (runtime).
- This is achieved using the try, except, else, and finally blocks.

try: contains the code which may raise an exception.


except: responsible for handling the exception, will be called when one ore more error(s) are raised
else: will be called when no exception is raised
finally: will be called irrespective of any exception being raised

Syntax and Usage


Basic Structure
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")

Multiple Exceptions
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
except ValueError:
print("Invalid value!")

Catching All Exceptions: except clause catches all exceptions but is generally discouraged
because it can catch unexpected exceptions, including system-exiting exceptions.
try:
risky_code()
except:
print("An error occurred!")

Accessing Exception Information


You can access information about the exception using the as keyword.
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error occurred: {e}")

else Clause
The else block runs if no exceptions were raised in the try block.
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero!")
else:
print(f"Result is {result}")

finally Clause
The finally block always executes, regardless of whether an exception was raised or not. It is
typically used for cleanup actions.
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero!")
finally:
print("Execution completed")
Custom Exceptions
You can define custom exceptions by creating a new class that inherits from the Exception class.
class CustomError(Exception):
def __init__(self, message):
self.message = message

try:
raise CustomError("This is a custom error")
except CustomError as e:
print(f"Caught custom exception: {e.message}")

File Handling in Python

Key Concepts
1. File Operations: Python allows for various file operations such as opening, reading,
writing, and closing files.
2. File Modes: Different modes dictate how the file is accessed (e.g., read, write, append).

Basic File Operations


Opening a File
The open() function is used to open a file. It returns a file object and takes two parameters: the
file name and the mode.

file = open("example.txt", "r") # Open file for reading

File Modes
Mode Description
r Read mode. Default mode. Opens a file for reading.
Write mode. Opens a file for writing (If the file already exists, its contents are truncated (deleted), and
w
a new file is created with the same name. If the file does not exist, a new one is created.).
a Append mode. Opens a file for appending (creates a new file if it doesn't exist).
b Binary mode. Opens a file in binary mode.
t Text mode. Default mode. Opens a file in text mode.
x Exclusive creation mode. Creates a new file, fails if the file already exists.

Reading from a File


You can read the contents of a file using various methods:
• read(): Reads the entire file.
• read(n): used to read n bytes (from the filter pointer location)
• readline(): Reads one line at a time.
• readlines(): Reads all lines into a list.
with open("example.txt", "r") as file:
content = file.read()
print(content)
with open("example.txt", "r") as file:
line = file.readline()
print(line)

with open("example.txt", "r") as file:


lines = file.readlines()
print(lines)

Writing to a File
You can write to a file using the write() method. If the file does not exist, it will be created.
with open("example.txt", "w") as file:
file.write("Hello, world!")

with open("example.txt", "a") as file:


file.write("\nAppending a new line.")

Closing a File
Although using the with statement automatically closes the file, you can also manually close a file
using the close() method.
file = open("example.txt", "r")
# Perform file operations
file.close()

File Management
Checking if a File Exists
The os module provides methods to check if a file exists.
import os
if os.path.exists("example.txt"):
print("File exists.")
else:
print("File does not exist.")

Deleting a File
You can delete a file using the remove() method from the os module.
import os
os.remove("example.txt")

Advanced File Handling


Reading and Writing Binary Files
Binary files can be handled by opening them in binary mode (b).
with open("example.bin", "wb") as file: # Writing binary data
file.write(b'\x00\x01\x02\x03')
with open("example.bin", "rb") as file: # Reading binary data
data = file.read()
print(data)
File Positioning
You can control the file pointer using seek() and tell() methods.
with open("example.txt", "r") as file:
file.seek(10) # Move to the 10th byte
position = file.tell() # Get the current position
print(position)
content = file.read()
print(content)

Working with CSV Files


The csv module simplifies reading and writing CSV files.

import csv

# Writing to a CSV file


with open("example.csv", "w", newline='') as file:
writer = csv.writer(file)
writer.writerow(["Name", "Age", "City"])
writer.writerow(["Alice", 30, "New York"])
writer.writerow(["Bob", 25, "Los Angeles"])

# Reading from a CSV file


with open("example.csv", "r") as file:
reader = csv.reader(file)
for row in reader:
print(row)

Strings
• collection of characters
• Immutable. However, you can create new strings based on operations
performed on existing strings.

Creating Strings

single_quote_str = 'Hello, World!'


double_quote_str = "Hello, World!"
triple_single_quote_str = '''Hello,
World!'''
triple_double_quote_str = """Hello,
World!"""

print(single_quote_str) # Output: Hello, World!


print(double_quote_str) # Output: Hello, World!
print(triple_single_quote_str) # Output: Hello,
# World!
print(triple_double_quote_str) # Output: Hello,
# World!

String Operations
# Concatenation
greeting = "Hello, " + "World!"
print(greeting) # Output: Hello, World!

# Repetition
repeated_greeting = "Hello! " * 3
print(repeated_greeting) # Output: Hello! Hello! Hello!

# Length
length_of_greeting = len(greeting)
print(length_of_greeting) # Output: 13

# Indexing
first_char = greeting[0]
print(first_char) # Output: H

# Slicing
substring = greeting[0:5]
print(substring) # Output: Hello

Formatting Strings

Using the format() Method


name = "Alice"
age = 30
formatted_str = "Name: {}, Age: {}".format(name, age)
print(formatted_str) # Output: Name: Alice, Age: 30

String Interpolation
name = "Alice"
age = 30
formatted_str = "Name: %s, Age: %d" % (name, age)
print(formatted_str) # Output: Name: Alice, Age: 30

String Encoding and Decoding


s = "Hello, World!"
b = s.encode("utf-8")
print(b) # Output: b'Hello, World!'

s = b.decode("utf-8")
print(s) # Output: Hello, World!

Raw Strings
Use r prefix to treat backslashes as literal characters.
raw_str = r"This is a raw string with a newline \n"
print(raw_str) # Output: This is a raw string with a newline \n

Common Use Cases


Checking Substrings
s = "Hello, World!"
if "World" in s:
print("Found!") # Output: Found!
Reversing a String
s = "Hello, World!"
reversed_s = s[::-1]
print(reversed_s) # Output: !dlroW ,olleH

String Methods

Method Description Syntax Parameters Returns Example


Capitalizes the first
New 'hello'.capitalize() ->
capitalize() character of the str.capitalize() None
string 'Hello'
string.
Converts all
New 'HELLO'.lower() ->
lower() characters to str.lower() None
string 'hello'
lowercase.
Converts all
New 'hello'.upper() ->
upper() characters to str.upper() None
string 'HELLO'
uppercase.
Converts the first
New 'hello world'.title() ->
title() character of each str.title() None
string 'Hello World'
word to uppercase.
Swaps the case of all New 'Hello'.swapcase() ->
swapcase() str.swapcase() None
characters. string 'hELLO'
Returns the lowest
Index or -
find() index of the str.find(sub) sub 'hello'.find('l') -> 2
1
substring if found.
Returns the lowest
index of the
index() substring, raises str.index(sub) sub Index 'hello'.index('l') -> 2
ValueError if not
found.
Returns the count of
non-overlapping
count() str.count(sub) sub Integer 'hello'.count('l') -> 2
occurrences of the
substring.
Replaces
occurrences of a New 'hello'.replace('l', 'x') -
replace() str.replace(old, new) old, new
substring with string > 'hexxo'
another substring.
Removes leading
New ' hello '.strip() ->
strip() and trailing str.strip() None
string 'hello'
whitespace.
Splits the string at
List of 'a,b,c'.split(',') -> ['a',
split() the specified str.split(delim) delim
strings 'b', 'c']
delimiter.
Joins elements of an
New ','.join(['a', 'b', 'c']) ->
join() iterable with the str.join(iterable) iterable
string 'a,b,c'
string as a separator.
Returns True if the
'hello'.startswith('he')
startswith() string starts with the str.startswith(prefix) prefix Boolean
-> True
specified prefix.
Method Description Syntax Parameters Returns Example
Returns True if the
'hello'.endswith('lo') -
endswith() string ends with the str.endswith(suffix) suffix Boolean
> True
specified suffix.
Formats the string '{} {}'.format('Hello',
New
format() using the provided str.format(args) args 'World') -> 'Hello
string
arguments. World'
Returns True if all
isdigit() characters in the str.isdigit() None Boolean '123'.isdigit() -> True
string are digits.
Returns True if all
'abc'.isalpha() ->
isalpha() characters in the str.isalpha() None Boolean
True
string are alphabetic.
Returns True if all
characters in the 'abc123'.isalnum() ->
isalnum() str.isalnum() None Boolean
string are True
alphanumeric.

Para
Return
Method Description Syntax meter Example Output
s
s
xpands tabs tabsize 'hello\
Expandtabs in the string str.expandtabs(tabsize) (optio tworld'.expandtabs(4 'hello world'
() to spaces. nal) )
Converts the
string to
lowercase None New
casefold() str.casefold() 'Hello'.casefold() 'hello'
suitable for string
caseless
comparison.
width,
Centers the
fillcha
string in a New
center() str.center(width[, fillchar]) r 'hello'.center(10, '-') '--hello---'
field of a string
(optio
given width.
nal)

Format Types
Format Type Description Example Output
"{:<10}".format("Hell
:< Left-align within the specified width Hello
o")
"{:>10}".format("Hell
:> Right-align within the specified width Hello
o")
"{:^10}".format("Hell
:^ Center-align within the specified width Hello
o")
:0 Pad with zeros "{:05}".format(42) 00042
"{:10}".format("Hello
Width Minimum width of the output Hello
")
Number of digits after the decimal point for floating- "{:.2f}".format(3.141 3.14
Precision 59)
point numbers
d Decimal integer "{:d}".format(255) 255
x Hexadecimal (lowercase) "{:x}".format(255) ff
X Hexadecimal (uppercase) "{:X}".format(255) FF
b Binary "{:b}".format(255) 11111111
Format Type Description Example Output
o Octal "{:o}".format(255) 377
"{:.2f}".format(3.141
f Fixed-point number 3.14
59)
"{:.2e}".format(3.141
e Exponential notation (lowercase) 3.14e+00
59)
"{:.2E}".format(3.141
E Exponential notation (uppercase) 3.14E+00
59)
"{:s}".format("Hello"
s String (default) Hello
)
% Percentage "{:.2%}".format(0.25) 25.00%

module

- file with .py extension


- collection of variables, functions, classes
__name__ is used to get the name of a module
__main__ is the module name of currently executing module
# page: page1.py
num = 100
# the file with nane page1.py is representing a module with name page1

importing a module

# mymodule.py
class Person:
pass
def my_function():
pass

# page1.py
# import all the entities from mymodule
import mymodule
p1 = mymodule.Person()

# page2.py
# import only Person class from mymodule
from mymodule import Person
p1 = Person()

# page3.py
# MyPerson will be created as an alias of Person
from mymodule import Person as MyPerson
p1 = MyPerson()

# page4.py
# mm will be created as an alias for mymodule
import mymodule as mm
p1 = mm.Person()

package
- collection of modules
- folder with a file named __init__.py
e.g.
# mypackage (package)
# - files (sub-package)
# - myfile (module)
# - Person (class)
# - Car (class)

# from mypackage.files.myfile import Person


# p1 = Person()
# from mypackage.files.myfile import Car
# c1 = Car()
### *Beginner Level*
1. *Introduction to Python*
- History and Features of Python
- Installing Python (Windows, macOS, Linux)
- Python IDEs (IDLE, PyCharm, VS Code)

2. *Basic Syntax*
- Variables and Data Types (int, float, str, bool)
- Basic Operators (Arithmetic, Comparison, Logical)
- Control Flow (if, else, elif)
- Loops (for, while, nested loops)
- Comments and Docstrings

3. *Data Structures*
- Lists (creation, indexing, slicing, methods)
- Tuples (immutability, packing/unpacking)
- Dictionaries (key-value pairs, methods)
- Sets (unique elements, set operations)

4. *Functions*
- Defining and Calling Functions
- Function Arguments (default, keyword, arbitrary)
- Return Values
- Lambda Functions
- Scope and Lifetime of Variables

5. *Modules and Packages*


- Importing Modules (standard and third-party)
- Creating and Using Packages
- The __init__.py File
- Exploring the Standard Library

6. *File Handling*
- Reading and Writing Text Files
- Working with CSV Files
- JSON Serialization and Deserialization
- File Methods and Context Managers

### *Intermediate Level*


1. *Object-Oriented Programming (OOP)*
- Classes and Objects
- Attributes and Methods
- Inheritance (single and multiple)
- Polymorphism
- Encapsulation and Data Hiding
- Special Methods (__init__, __str__, __repr__)

2. *Exception Handling*
- Try, Except, Finally Blocks
- Raising Exceptions
- Custom Exception Classes
- Handling Multiple Exceptions

3. *Advanced Data Structures*


- List Comprehensions
- Dictionary Comprehensions
- Sets and Frozensets
- Collections Module (namedtuple, deque, Counter)

4. *Iterators and Generators*


- Iterators and the Iterator Protocol
- Creating Generators with yield
- Generator Expressions
- Using itertools for Advanced Iteration

5. *Decorators*
- Function Decorators
- Class Decorators
- Using functools.wraps
- Practical Use Cases (logging, access control)

6. *Regular Expressions*
- Basic Patterns and Syntax
- Matching and Searching
- Substitution and Splitting
- Using the re Module

### *Advanced Level*


1. *Advanced OOP*
- Metaclasses and Custom Metaclasses
- Abstract Base Classes (ABCs)
- Method Resolution Order (MRO)
- Property Decorators (@property, @setter, @deleter)

2. *Concurrency*
- Multithreading (threading module)
- Multiprocessing (multiprocessing module)
- Asynchronous Programming (asyncio, await, async)
- Concurrent Futures

3. *Networking*
- Sockets (TCP/IP, UDP)
- HTTP Requests (using requests library)
- Web Scraping (BeautifulSoup, Scrapy)
- Building Simple Web Servers

4. *Database Interaction*
- SQL Basics (CRUD operations)
- SQLite (using sqlite3 module)
- Object-Relational Mapping (ORM) with SQLAlchemy
- NoSQL Databases (MongoDB with PyMongo)

5. *Testing*
- Unit Testing (unittest, pytest)
- Integration Testing
- Mocking and Patching
- Test-Driven Development (TDD)

6. *Memory Management*
- Understanding Memory Allocation
- Garbage Collection
- Memory Profiling (using memory_profiler, tracemalloc)
- Optimizing Memory Usage

### *Expert Level*


1. *Performance Optimization*
- Profiling and Benchmarking (cProfile, timeit)
- Cython for Performance Boosts
- Just-In-Time Compilation (PyPy)
- Optimizing Code with NumPy

2. *Advanced Libraries and Frameworks*


- NumPy (arrays, vectorization)
- Pandas (data manipulation, DataFrames)
- TensorFlow and PyTorch (machine learning)
- Django and Flask (web development)

3. *Security*
- Cryptography (using cryptography library)
- Secure Coding Practices
- Authentication and Authorization
- Secure Communication (SSL/TLS)

4. *Deployment*
- Docker (containerization)
- Continuous Integration/Continuous Deployment (CI/CD)
- Cloud Deployment (AWS, Azure, GCP)
- Serverless Computing

5. *Metaprogramming*
- Introspection (using dir(), getattr(), setattr())
- Code Generation (using exec(), eval())
- Decorators and Metaclasses
- Dynamic Code Execution

6. *Advanced Topics*
- Design Patterns (Singleton, Factory, Observer)
- Domain-Specific Languages (DSLs)
- Advanced Algorithms and Data Structures
- Contributing to Open Source Projects

You might also like