- Print Output
- Variable
- Data Types & Type Conversion
- Control Flow & Short Handif
- Function & it's Arguments
- Decorators
- For & While Loop
- String
- List
- Tuple
- Set
- Dictionary
- Map, Filter & List Comprehension
- File in Python
- Import & Export
- Iterators & Generators
- Error Handling
- OOPs
- Built-in Functions
- Check Program Performance
- Python Library
# Print Somthing
print("Hello World") # Hello World
name = "John Doe"
age = 30
# Print Multiple Data
print(name, age) # John Doe 30
# Print Horizontally - Default end="\n"
for item in range(5):
print(item, end=' ') # 0 1 2 3 4
# Escape Sequences
print("Hello \'World\'") # Hello 'World'txt = "Hello World"
num = 2021
is_login = True
string = str(1)
# Assaign Multiple Variable
name, age = 'John Doe', 30# Most Used Built-in Data Types in Python
1. str -> 'Hey'
2. int -> 100
3. float -> 10.1
4. bool -> True/False
5. list -> [1, 2, 3]
6. tuple -> (1, 2, 3)
7. set -> {1, 2, 3}
8. dict -> {'name': 'John Doe', 'age': 30}
9. range -> range(5)
10. complex -> 1j
# Type Checking Method
type([1, 2, 3]) # <class 'list'>int('100') # String -> Integer
list((1, 2, 3)) # Tuple -> List
tuple([1, 2, 3]) # List -> Tuple
set([1, 2, 3]) # List -> Set
# Also Change Data Type Using *
tpl = (1, 2, 3)
tpl_to_list = [*tpl]
print(tpl_to_list) # [1, 2, 3]# Normal Function Defination
def add (num1, num2):
return num1 + num2
print(add(25, 10)) # 35
# Set a Default Argument
def say_hello (name, greeting="Hello"):
return f"{greeting}, {name}"
print(say_hello("John", 'Hey')) # Hey, John# xargs => return a Tuple
def get_nums (*nums):
return nums
print(get_nums(2, 3, 4, 5, 6)) # (2, 3, 4, 5, 6)
# xxargs => return a Dictionary
def get_data (**data):
return data
print(get_data(name='John Doe', age=20)) # {'name': 'John Doe', 'age': 20}# lambda arguments : expression
func1 = lambda x, y: x + y
print(func1(1, 2)) #3
func2 = lambda x, y=2: x + y
print(func2(1)) #3
func3 = lambda *args: args
print(func3(1, 2)) #(1, 2)
func4 = lambda **args: args
print(func4(name='John Doe', age=30)) #{'name': 'John Doe', 'age': 30}
# lmbda IIFE
(lambda num1, num2: num1 * num2)(10, 5)# Factorial Program
def factorial(num):
if num == 1:
return 1
else:
return num * factorial(num-1)
print(factorial(5)) # 120# before using decorator
def setup(func):
def wrapper():
print("Start Executing")
func()
print("End Executing")
return wrapper
def test_login():
print("Login Test")
setup(test_login)()
# or
result = setup(test_login)
result()
# Start Executing
# Login Test
# End Executing
# using decorators
def setup(func):
def wrapper():
print("Start Executing")
func()
print("End Executing")
return wrapper
@setup
def test_login():
print("Login Test")
test_login()
# Start Executing
# Login Test
# End Executing# parameterized decorated method
def before_after(func):
def wrapper(*args, **kwargs):
print("Before")
func(*args, **kwargs)
print("After")
return wrapper
@before_after
def execute_script(feature):
print(feature, "Script Executed")
execute_script("Login")
# Before
# Login Script Executed
# After# return decorated method
def setup(func):
def wrapper(*args):
print("Start Executing")
val = func(*args)
print("End Executing")
return val
return wrapper
@setup
def test_login(feature):
return f"{feature} Test"
print(test_login("Login"))
# Start Executing
# End Executing
# Login Test# A good example of decorator
import time
def check_execution_time(func):
def wrapper():
before = time.time()
func()
print(f"Execution Time = {time.time() - before} seconds")
return wrapper
@check_execution_time
def take_rest():
time.sleep(2)
take_rest() # Execution Time = 2.001185894012451 secondshigh_income, good_credit, student = True, True, True
if high_income and good_credit and not student:
print("Eligible")
else:
print("Not Eligible") # Not Eligible
# Chaining Comparison Operators
age = 35
if 18 < age < 65:
print("Eligible") # Eligible
else:
print("Not Eligible")temperature = 45
weather = "Cold" if temperature <= 30 else "Warm" if 30 < temperature <= 60 else "Hot" # Warmcounter = 0
while (counter <= 10):
counter += 1
if counter == 3:
continue
if counter > 5:
break
print(counter) # 1 2 4 5for item in range(0, 11, 2):
print(item, end=' ') # Print Even: 0 2 4 6 8 10
# List Comprehension [Expression for item in items]
li = [item for item in range(1, 5)]
print(li) # [1, 2, 3, 4]When loop completed, then the 'StopIteration Exception' & 'else' will be execute.
for item in range(1,4):
print(item)
else:
print('Item Finished!')
# 1 2 3
# Item Finished!If loop not finished, 'StopIteration Exception' & 'else' won't be executed.
for i in range(1, 5):
if i > 3:
break
print(i)
else:
print('Iteration Complete!')
# 1 2 3A Good Example of Loop Exception
def check_prime(num):
for i in range(2, num):
if num % i == 0:
print(False)
break
else:
print(True)
# print(check_prime(17)) # True
# print(check_prime(13)) # True
# print(check_prime(10)) # Falsetxt = "Hello World"
print(txt[0], txt[-1]) # H d
print(txt[::-1]) # dlroW olleH
print(txt[4:1:-1]) # oll
print(txt.index('o')) # 4 (counting from Left)
print(txt.find('o')) # 4 (counting from Left)
print(txt.rindex('o')) # 7 (counting from Right)
print(txt.rfind('o')) # 7 (counting from Right)
print(txt.split(' ')) # ['Hello', 'world']
print(", ".join(txt.split(' '))) # Hello, world (join iterable elements into a string based on certain separator)
print(txt.replace('world', 'Python')) # Hello Python
print(txt.startswith('Hel')) # True
print(txt.endswith('H')) # False
print(txt.isdigit()) # False
print(txt.isnumeric()) # False
print(txt.upper()) # HELLO WORLD
print(txt.lower()) # hello world
print(txt.title()) # Hello World
print(txt.isupper(), txt.islower(), txt.istitle()) # False False False
print("Hell" in txt) # True# Translating String
data = ['John Doe', 'Chittagong-Bangladesh', '530 B-Block\nHalishahar']
formatted_data = [dt.translate(str.maketrans({' ': '_', '-': '_', '\n': '_'})).lower() for dt in data]
formatted_data # ['john_doe', 'chittagong_bangladesh', '530_b_block_halishahar']# String Formatting
msg = """
Hey {name}
How's it going?
"""
greeting = "Good {text}"
name = "John"
info = f"This is {name}"
msg.format(name="Joe") # Hey Joe\nHow's it going?
greeting.format(text="Morning") # Good Morning
info # This is Johnli = [1, 2, 3, 4, 5] (Mutable & CRUD Possible)
li = [1, 2, 3, 4, 5]
print(li[1], li[-1]) # 2 5
print(li[1:3]) # [2, 3]li1, li2 = [1, 2, 3], [4, 5, 6]
print(li1 + li2) # [1, 2, 3, 4, 5, 6]
print([*li1, *li2, 100]) # [1, 2, 3, 4, 5, 6, 100]
li1.extend(li2)
print(li1) # [1, 2, 3, 4, 5, 6]employees = ['John', 'Doe', 'Mike', 'Clark', 'David']
first_employee, *others, last_employee = employees
print(first_employee, others, last_employee) # John ['Doe', 'Mike', 'Clark'] Davidnums = [23, 33, 52, 65, 76, 28, 32]
even_nums = [num for num in nums if num % 2 == 0]
print(even_nums) # [52, 76, 28, 32]names = ['John', 'Doe']
names.append('David') # ['John', 'Doe', 'David'] (add at Last)
names.insert(0, 'Mike') # ['Mike', 'John', 'Doe', 'David'] (add at any specific position)names = ['Mike', 'John', 'Doe', 'David', 'Max', 'Joe', 'Root']
names.pop() # ['Mike', 'John', 'Doe', 'David', 'Max', 'Joe'] (remove item at Last)
names.pop(0) # ['John', 'Doe', 'David', 'Max', 'Joe'] (remove any item using index)
names.remove('John') # ['Doe', 'David', 'Max', 'Joe'] (remove any specific item)
del names[0:2] # ['Max', 'Joe'] (remove series of items)
names.clear() # [] (remove all items)nums = [23, 33, 52, 65, 76, 28, 32]
print(nums.sort()) # None (only sort the list and return None not list)
print(nums) # [23, 28, 32, 33, 52, 65, 76]
print(sorted(nums)) # [23, 28, 32, 33, 52, 65, 76] (return a list after sorting)
print(sorted(nums, reverse=True)) # [76, 65, 52, 33, 32, 28, 23] (sorting DESC order)
# Sorting Little Complex List
products = [('product1', 75), ('product2', 124), ('product3', 44)]
products.sort(key=lambda pd: pd[1])
print(products) # [('product3', 44), ('product1', 75), ('product2', 124)]
products.sort(key=lambda pd: pd[1], reverse=True)
print(products) # [('product2', 124), ('product1', 75), ('product3', 44)]emp = ['John', 'Joe', 'Max']
print(emp[::-1]) # ['Max', 'Joe', 'John']
print(emp.reverse()) # None
print(emp) # ['Max', 'Joe', 'John']
print(reversed(emp)) # <list_reverseiterator object at 0x000001EEA63FAC20>li = [32, 54, 32, 43]
print(li.index(32)) # 0
print(li.count(32)) # 2# print the index & value using enumerate()
nums = [23, 33, 52, 65]
for index, value in enumerate(nums):
print(index, value)
# 0 23
# 1 33
# 2 52
# 3 65# Check the List item existance
names = ['John', 'Doe', 'Foo', 'Bar']
print('John' in names) # True# Shortcut Create List
similar_nums = [4] * 10
print(similar_nums) # [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]Tuple => (Immutable & Read Only, Not possible to add, modify & delete item)
tpl = (10, 20, 30, 40, 50, 60) nums = 32, 42 or age = 32,
tpl = (10, 20, 30, 40, 50, 60)
print(tpl[2:5]) # (30, 40, 50)users = ("Joe", "John", "Root", "Justin", "Foo")
user_one, *other_users, last_user = users
print(user_one, other_users, last_user) # Joe ['John', 'Root', 'Justin'] Foo# Find the index of Tuple
users = ("Joe", "John", "Root", "Justin", "Joe")
print(users.index('John')) # 1
print(users.count('Joe')) # 2
print('Joe' in users) # True# Create a Generator using Tuple Comprehension
users = ("Joe", "John", "Root", "Justin", "Foo")
gen = (item for item in users)
print(type(gen)) # <class 'generator'>Set => Remove Duplicate, Possible to add, remove, delete item but not able to access specific item because it has no order
nums = {2, 3, 4, 5, 6}
print(set((22, 23, 22, 23))) # {22, 23}
print(set([54, 50, 50, 55])) # {50, 54, 55}nums = {2, 3, 4, 5, 6}
nums.add(10) # {2, 3, 4, 5, 6, 10}
nums.pop() # {3, 4, 5, 6, 10}
nums.remove(5) # {3, 4, 6, 10}
nums.clear() # set()a_set = {1, 2, 3, 4}
b_set = {2, 4, 5, 6}
print(a_set | b_set) # {1, 2, 3, 4, 5, 6}
# or
print(a_set.union(b_set)) # {1, 2, 3, 4, 5, 6}a_set = {1, 2, 3, 4}
b_set = {2, 4, 5, 6}
print(a_set & b_set) # {2, 4}
# or
print(a_set.intersection(b_set)) # {2, 4}a_set = {1, 2, 3, 4}
b_set = {2, 4, 5, 6}
print(a_set - b_set) # {1, 3}
# or
print(a_set.difference(b_set)) # {1, 3}a_set = {1, 2, 3, 4}
b_set = {2, 4, 5, 6}
print(a_set ^ b_set) # {1, 3, 5, 6}
# or
print(a_set.symmetric_difference(b_set)) # {1, 3, 5, 6}person = { 'name': 'John Doe', 'country': 'USA', 'age': 30 }
person = { 'name': 'John Doe', 'country': 'USA', 'age': 30 }
print(person['name']) # John Doe (Throw KeyError exception, if key is not exist)
print(person.get('name')) # John Doeuser = {'name': 'Joe', 'email': 'joe@joe.com', 'phone': '456-888-2223'}
usr_data = [data for _, data in user.items()]
print(usr_data) # ['Joe', 'joe@joe.com', '456-888-2223']
nums = {x: x * x for x in range(1, 6)}
print(nums) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}person = { 'name': 'John Doe', 'country': 'USA', 'age': 30 }
person['city'] = 'Brooklyn' # {'name': 'John Doe', 'country': 'USA', 'age': 30, 'city': 'Brooklyn'} (dict key should be unique)
person.pop('age') # {'name': 'John Doe', 'country': 'USA', 'city': 'Brooklyn'}
person.update({'name': 'Joe', 'email': 'joe@joe.com'})
# {'name': 'Joe', 'country': 'USA', 'city': 'Brooklyn', 'email': 'joe@joe.com'}
person.clear() # {}person = { 'name': 'John Doe', 'country': 'usa', 'age': 30 }
print(person.keys()) # dict_keys(['name', 'country', 'age'])
print(person.values()) # dict_values(['John Doe', 'usa', 30])
print(person.items()) # dict_items([('name', 'John Doe'), ('country', 'usa'), ('age', 30)])# Print the Keys of Dictionary
person = { 'name': 'John Doe', 'country': 'usa', 'age': 30 }
for key in person:
print (key) # name country age
# Print the Values of Dictionary
for key in person:
print (person[key]) # John Doe usa 30products = [('product1', 75), ('product2', 124), ('product3', 44)]
# Map VS List Comprehension (Pythonic)
product_prices = list(map(lambda pd: pd[1], products)) # [75, 124, 44]
pd_prices = [price for _, price in products] # [75, 124, 44]
# Filter VS List Comprehension
costly_products = list(filter(lambda pd: pd[1] > 50, products)) # [('product1', 75), ('product2', 124)]
costly_products = [pd for pd in products if pd[1] > 50] # [('product1', 75), ('product2', 124)]with open('hello.txt', 'w') as fp:
fp.write('Hello World\n')
fp.write('Another Text\n')
fp.write('Python is Awesom\n')with open('hello.txt', 'r') as fp:
print(fp.read())
# Hello World
# Another Text
# Python is Awesomlines = []
with open('hello.txt', 'r') as fp:
for line in fp.readlines():
lines.append(line)
print(lines)
# ['Hello World\n', 'Another Text\n', 'Python is Awesom\n']with open('hello.txt', 'r') as fp:
print(fp.readline())
# Hello Worldwith open('hello.txt', 'a') as fp:
fp.write('Another line added in append mode')
with open('hello.txt', 'r') as fp:
print(fp.read())
# Hello World
# Another Text
# Python is Awesom
# Another line added in append modeimport my_module
my_module.find_index()
import my_module as mm
mm.find_index()
from my_module import find_index
find_index()
from my_module import find_index as fi # Ambiguous => not recommended
fi()
from my_module import * # Ambiguous => not recommended
find_index()Use Custom Module in Anywhere
We can import a module by adding the path of it as PYTHONPATH in User variables.
Key => PYTHONPATH
Value => c:\users\john\documents\my_module
# To see which paths are looking for importing module
import sys
sys.path| yield | return |
|---|---|
| provide output and continue | provide output and stop |
| gives back a generator | gives a return value and stop |
| keeps the states of local variable | destroys the states of local variable |
| not exit the function | exit the function |
yield statement actually pause the execution of function and store the value in local scope and continue this process by next() method sincie yield convert a function to a generator.
Why Generator: When we only care about the current value, not worry about the before, after or all values, then we can go with Generator. because it only cares about the current value not the whole data. so it's more memory efficient.
def sqr_num(n):
for i in range(1, n + 1):
yield i * i
for i in sqr_num(5): # default behavior of for loop => iter(range(5))
print(i) # default behavior of for loop => next(iterable)| Keyword | Definition |
|---|---|
| try | will try to execute the script/code |
| except | will execute once any exception found |
| else | will execute if no exection found |
| finally | always it will execute - exception found or not |
def get_div(a, b):
try:
result = a / b
except ZeroDivisionError:
print("You can't divided by Zero")
except TypeError:
print("You can't divided by String")
else:
print(result)
finally:
print('Operation is Completed!')
get_div(3, 5)
# 0.6
# Operation is Completed!
get_div(3, 0)
# You can't divided by Zero
# Operation is Completed!
get_div(3, '4')
# You can't divided by String
# Operation is Completed!Example
class Person:
lang = 'English'
# __init__ is working like a constructor in other lang.
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# self is instance obj. It must be provided other wise method doesn't work perfectly
def get_summary(self):
return f"Name: {self.name}, Age: {self.age}, Gender: {self.gender}"
ps = Person('John Doe', 25, 'Male')
print(ps) # <__main__.Person object at 0x7ff86530b040>
print(ps.__dict__) # {'name': 'John Doe', 'age': 25, 'gender': 'Male'}
print(ps.name) # John Doe
print(ps.get_summary()) # Name: John Doe, Age: 25, Gender: Male# create class dynamically by using type()
# farmula: ClassName = type('ClassName', (Parent1, Parent2), {}/dict() => to create property)
Person = type('Person', (Animal), {'lang': 'English', 'name': 'John'})
p = Person() # <__main__.Person object at 0x000001F325CB0B20>class Person:
person_id = 1000
def __init__(self, name, email):
self.name = name
self.email = email
Person.person_id += 1
def get_data(self):
return f"ID: {self.person_id}, Name: {self.name}, Email: {self.email}"
@classmethod
def generate_dummy(cls):
return cls("Dummy", "dummy@dummy.com")
person1 = Person("Joe", "joe@joe.com")
print(person1.get_data()) # ID: 1001, Name: Joe, Email: joe@joe.com
person2 = Person("John", "john@john.com")
print(person2.get_data()) # ID: 1002, Name: Joe, Email: joe@joe.com
dummy = Person.generate_dummy()
print(dummy.get_data()) # ID: 1003, Name: Dummy, Email: dummy@dummy.comclass Square:
def __init__(self, length):
self.length = length
self._area = self.length * self.length
@property
def area(self):
return self._area
@area.setter
def area(self, val):
self._area = val
def __eq__(self, other):
return self.length == other.length
def __gt__(self, other):
return self.length > other.length
def __add__(self, other):
return f"Square({self.length + other.length})"
sq1 = Square(5)
sq2 = Square(3)
print(sq1.area) # 25
sq1.area = 100 # 100
print(sq1.area)
print(sq1 == sq2) # False
print(sq1 > sq2) # True
print(sq1 < sq2) # False
print(sq1 + sq2) # Square(8)Protect the code from unwanted access. variable should be private and based on need getter and setter method should be created
class Author:
def __init__(self):
self.__authors = {}
def add_author_post(self, author):
self.__authors[author.lower()] = self.__authors.get(author.lower(), 0) + 1
def __getitem__(self, author):
return self.__authors.get(author.lower(), 0)
def __setitem__(self, author, post_count):
self.__authors[author.lower()] = post_count
def __len__(self):
return len(self.__authors)
def __iter__(self):
return iter(self.__authors)
def __str__(self):
return str(self.__authors)
author = Author()
author.add_author_post('John')
author.add_author_post('john')
author.add_author_post('joe')
author['mike'] = 15
print(author) # {'john': 2, 'joe': 1, 'mike': 15}
print(len(author)) # 3
print(author['john']) # 2
for author in author:
print(author) # john joe mikeTransfer common data from parent class to child class. Python supports multiple inheritance.
class Person:
def __init__(self, name, email):
self.name = name
self.email = email
class Employee(Person):
def dream(self):
pass
class Teacher(Person):
def teach(self):
pass
class EmployeeTeacher(Employee, Teacher):
pass
emp = Employee("Joe", "joe@joe.com")
print(isinstance(emp, Person)) # True
print(isinstance(emp, Employee)) # True
print(issubclass(Person, object)) # True
print(issubclass(Employee, Person)) # True# Extending Built-in Types by Inheritance
class ListLogger(list):
def append(self, obj):
print("append called.")
super().append(obj)
list = ListLogger()
list.append(100) # append called.
print(list) # [100]Hide the implementation part, showing only the outcome. It's like HALF BAKED COOKIES, not ready to eat. can't create object for Abstract class.
from abc import ABC, abstractmethod
class InvalidOperationError(Exception):
pass
class Stream(ABC):
def __init__(self):
self.opened = False
def open(self):
if self.opened:
raise InvalidOperationError("Stream already open")
self.opened = True
def close(self):
if not self.opened:
raise InvalidOperationError("Stream already close")
self.opened = False
@abstractmethod
def read(self):
pass
class FileStream(Stream):
def read(self):
print("Reading Data from File")
class NetworkStream(Stream):
def read(self):
print("Reading Data from Network")class Rectangle:
def __init__(self, height, width):
self.height = height
self.width = width
def get_area(self):
return self.height * self.width
class Square(Rectangle):
def __init__(self, size):
self.size = size
def get_area(self):
return self.size * self.size
rc = Rectangle(5, 4)
print(rc.get_area()) # 20
sq = Square(5)
print(sq.get_area()) # 25all() retuns False, if any the of iterable object item is Falsy, Otherwise it returns True
print(all([])) # True
print(all([1, 2, 3])) # True
print(all([1, 2, 0])) # Falseany() returns False, if all of the iterable object item is Falsy or empty iterable like [], () etc. Otherwise it returns True
print(any([])) # False
print(any([1, 2, 3])) # True
print(any([1, 2, 0])) # True
print(any([0, False, ''])) # Falsedef get_double(item):
return item + item
mapped = map(get_double, [2, 3, 4])
print(mapped) # <map object at 0x0000023AF5BCA1F0>
# Readable map object
print(list(mapped)) # [4, 6, 8]
# Implement Map with magic lambda function
mapped_obj = map(lambda x: x + x, [2, 3, 4])
mapped_list = list(mapped_obj)
print(mapped_list) # Same [4, 6, 8]
# or Simply
print(list(map(lambda x: x + x, [2, 3, 4]))) # [4, 6, 8]
# We Can pass multiple iterable object as arg
print(list(map(lambda first_li_item, seccond_li_item: first_li_item + seccond_li_item, [1, 2, 3], [100, 200, 300])))
# [101, 202, 303]def get_adult(age):
if age > 18:
return age
filtered_age_obj = filter(get_adult, [22, 10, 12, 40, 32, 33, 15])
print(filtered_age_obj) # <filter object at 0x00000261B6F6A1F0>
filtered_age_list = list(filtered_age_obj)
print(filtered_age_list) # [22, 40, 32, 33]
# Implement filter() using lambda function
filtered_obj = filter(lambda age: age > 18, [22, 10, 12, 40, 32, 33, 15])
filtered_list = list(filtered_obj)
print(filtered_list) # [22, 40, 32, 33]
# Or Simply print in one line
print(list(filter(lambda age: age > 18, [22, 10, 12, 40, 32, 33, 15])))
# Exactly Same [22, 40, 32, 33]# default sorted function -> sorted(iterable, key=None, reverse=False)
# smaller -> bigger
print(sorted([11, 2, 43, 10, 50, 5, 7])) #[2, 5, 7, 10, 11, 43, 50]
# bigger -> smaller
print(sorted([11, 2, 43, 10, 50, 5, 7], key=None, reverse=True))
#[50, 43, 11, 10, 7, 5, 2]print(list(reversed([32,22,31]))) # [31, 22, 32]
print(tuple(reversed((32,22,31)))) # (31, 22, 32)
print(list(reversed((32,22,31)))) # [31, 22, 32]
# Reverse string
print(''.join(reversed('Hello World'))) # dlroW olleHprint(len([2,3,4])) # 3
print(len({'name': 'John', 'age': 30})) # 2
print(len('Hello')) # 5bd_players = ['Tamim Iqbal', 'Moshfiqur Rahim', 'Sakib Al Hasan', 'Mashrafi Mortaza', 'Mahmudullah Riad']
# Start Default -> 0
print(list(enumerate(bd_players, start=1)))
# [(1, 'Tamim Iqbal'), (2, 'Moshfiqur Rahim'), (3, 'Sakib Al Hasan'), (4, 'Mashrafi Mortaza'), (5, 'Mahmudullah Riad')]Pack the multiple iterable object
bd_players = ['Tamim Iqbal', 'Moshfiqur Rahim', 'Sakib Al Hasan', 'Mashrafi Mortaza', 'Mahmudullah Riad']
runs = [23, 55, 75, 10, 34]
wickets = [0, 0, 4, 2, 3]
print(list(zip(bd_players, runs, wickets)))
# [('Tamim Iqbal', 23, 0), ('Moshfiqur Rahim', 55, 0), ('Sakib Al Hasan', 75, 4), ('Mashrafi Mortaza', 10, 2), ('Mahmudullah Riad', 34, 3)]print(min([5, 2, 8, 1])) # 1
print(max([5, 2, 8, 1])) # 8print(sum([2, 3, 5])) # 10
print(sum((2, 3, 5))) # 10
print(sum({2, 3, 5})) # 10
# We can define a start value as 2nd arg
print(sum([2, 3], 10)) # 15divmod() takes two int as arguments and returns a tuple of two numbers where the 1st number is the quotient and the 2nd is the remainder.
print(divmod(10, 3)) # (3, 1)print(abs(-1)) # 1print(round(12.20)) # 12
print(round(12.55)) # 13print(pow(3,2)) # 9
print(pow(3,3)) # 27
print(pow(5,2)) # 25print(min(3, 2, 4, 7)) # 2
print(min([5, 2, 8, 1])) # 1print(max([5, 2, 8, 1])) # 8
print(max(10, 2, 8, 1)) # 10print([*range(5)]) # [0, 1, 2, 3, 4]
print([*range(0, 5, 2)]) # [0, 2, 4]print(format(10, '.2%')) # 1000.00%
print(format(100, 'b')) # 1100100 (Binary of 100)
print(format(100, 'o')) # 144 (Octal of 100)
print(format(1000, 'x')) # 3e8 (hex of 1000)
print(format(1000, 'X')) # 3E8 (hex of 1000)
print(format(10.0040, '.1f')) # 10.0
print(format(100000, ',')) # 100,000
print(format(100000, 'n')) # 100000
print(format(3.13592, '.2g')) # 3.1print(eval('2 + 5')) # 7chr(), ord()
print(ord('a')) # 97
print(chr(97)) # aiter(), next() iter() function is used to create iterable object & next() is used to access the item of Iterable Object.
itr = iter([5,2,3])
print(type(itr)) # <class 'list_iterator'>
print(next(itr)) # 5name = input('Please type your name: ')
print(name)int(), bin(), oct(), hex(), format(value, first chr of number system)
print(int('10')) # 10
print(type(int('10'))) # <class 'int'>
print(int(0b1010)) # 10
print(bin(10)) # 0b1010
print(oct(70)) # 0o106
print(hex(1000)) # 0x3e8
print(format(1000, 'x')) # 3e8 (hex of 1000)dir() function returns list of the attributes and methods of any object like functions , modules, strings, lists, dictionaries etc. If no argument passed, it returns the list of names in the current local scope.
print(dir())
# ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
print(dir(list))
# ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
print(dir(tuple))
# ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']vars() provides the built in function provided by python standard library. The vars() function returns the dic attribute of an object. The dict attribute is a dictionary containing the object's changeable attributes.
name = "Justin"
print(vars())
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f5182a994c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'Program/builtin.py', '__cached__': None, 'name': 'Justin'}
print(vars(list))
# {'__repr__': <slot wrapper '__repr__' of 'list' objects>, '__hash__': None, '__getattribute__': <slot wrapper '__getattribute__' of 'list' objects>, '__lt__': <slot wrapper '__lt__' of 'list' objects>, '__le__': <slot wrapper '__le__' of 'list' objects>, '__eq__': <slot wrapper '__eq__' of 'list' objects>, '__ne__': <slot wrapper '__ne__' of 'list' objects>, '__gt__': <slot wrapper '__gt__' of 'list' objects>, '__ge__': <slot wrapper '__ge__' of 'list' objects>, '__iter__': <slot wrapper '__iter__' of 'list' objects>, '__init__': <slot wrapper '__init__' of 'list' objects>, '__len__': <slot wrapper '__len__' of 'list' objects>, '__getitem__': <method '__getitem__' of 'list' objects>, '__setitem__': <slot wrapper '__setitem__' of 'list' objects>, '__delitem__': <slot wrapper '__delitem__' of 'list' objects>, '__add__': <slot wrapper '__add__' of 'list' objects>, '__mul__': <slot wrapper '__mul__' of 'list' objects>, '__rmul__': <slot wrapper '__rmul__' of 'list' objects>, '__contains__': <slot wrapper '__contains__' of 'list' objects>, '__iadd__': <slot wrapper '__iadd__' of 'list' objects>, '__imul__': <slot wrapper '__imul__' of 'list' objects>, '__new__': <built-in method __new__ of type object at 0x905e20>, '__reversed__': <method '__reversed__' of 'list' objects>, '__sizeof__': <method '__sizeof__' of 'list' objects>, 'clear': <method 'clear' of 'list' objects>, 'copy': <method 'copy' of 'list' objects>, 'append': <method 'append' of 'list' objects>, 'insert': <method 'insert' of 'list' objects>, 'extend': <method 'extend' of 'list' objects>, 'pop': <method 'pop' of 'list' objects>, 'remove': <method 'remove' of 'list' objects>, 'index': <method 'index' of 'list' objects>, 'count': <method 'count' of 'list' objects>, 'reverse': <method 'reverse' of 'list' objects>, 'sort': <method 'sort' of 'list' objects>, '__doc__': 'Built-in mutable sequence.\n\nIf no argument is given, the constructor creates a new empty list.\nThe argument must be an iterable if specified.'}It always returns the global scope data. either inside of funtion of outside of a function.
name = "Justin"
print(globals())
# Output {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f69628e04c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'Program/builtin.py', '__cached__': None, 'name': 'Justin'}It returns only function local scope data, if we use it inside a function if we use it in globle scope, it will react like globals() - I mean, return the global scope data.
name = "Justin"
print(locals())
# Output {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f69628e04c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'Program/builtin.py', '__cached__': None, 'name': 'Justin'}
def diff_locals_and_globals():
age = 20
print(globals())
print(locals())
diff_locals_and_globals()
# globals() Output -> {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fe5c69dc4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'Program/builtin.py', '__cached__': None, 'name': 'Justin', 'diff_locals_and_globals': <function diff_locals_and_globals at 0x7fe5c6885dc0>}
# locals() Output -> {'age': 20}id() is a adresss of the object in memory. It returns the unique identity of an object.
print(id('John')) # 140434664974640
print(id(10)) # 9788896
print(id([21, 54, 65])) # 139834604658304
print(id({'name': 'Doe'})) # 140615104266112hasattr() setattr(), getattr(), delattr()
class Person:
pass
ps = Person()
print(hasattr(ps, 'name')) # False
setattr(ps, 'name', 'John Foo')
print(hasattr(ps, 'name')) # True
print(getattr(ps, 'name')) # John Foo
delattr(ps, 'name')
print(hasattr(ps, 'name')) # Falsebool() is used to check the Truthy & Falsy value
print(bool(0)) # False
print(bool(1)) # True
print(bool([]), bool([100, 200])) # False Truetype() is used to check the data type
print(type('he he')) # <class 'str'>
print(type(['hey', 'hello'])) # <class 'list'>
print(type(20)) # <class 'int'>class Rectangle:
def __init__(self, height, width):
self.height = height
self.width = width
def get_area(self):
return self.height * self.width
class Square(Rectangle):
pass
rc = Rectangle(5, 4)
sq = Square(5, 5)
print(isinstance(rc, Rectangle)) # True
print(isinstance(sq, Rectangle)) # True
print(isinstance(sq, Square)) # True
print(isinstance(rc, Square)) # False
print(issubclass(Square, Rectangle)) # True
print(issubclass(Rectangle, Square)) # Falseopen()
__import__
ascii()
slice()
callable()
help()
hash()
breakpoint()
exec()
classmethod()
super()
property()
bytes()
bytearray()
object()
memoryview()
staticmethod()
repr()
compile()
complex()Compare the List & Deque Efficiency in the time of adding data at 0 index.
from timeit import timeit
from collections import deque
li = [item for item in range(10000)]
dq = deque(li)
print(timeit('li.insert(0, 100)', number=100000, globals=globals()))
# 2.143603781998536
print(timeit('dq.appendleft(100)', number=100000, globals=globals()))
# 0.006301867000729544# Var & Method
import typing
from typing import Any
name: str = "john"
age: int = 25
monthly_income: float = 6025.67
is_eligible: bool = True
random_var: Any = "hello"
random_var = 100
def greeting(name: str) -> str:
return f"hello, {name}"
def print_hello() -> None:
print("Hello World")# list, dict, set
from typing import List, Dict, Set, Any
li: List[List[int]] = [[1, 2], [3, 4]]
dt: Dict[str, Any] = {"name": "john", "email": "john@gmail.com", "age": 25}
nums: Set[bool] = {20, 32, 23, 43, 20, 30, 30}# custom type
from typing import List, Dict
User = Dict[str, str]
Users = List[User] # List[Dict[str, str]]
def get_front_user(usr: Users) -> User:
return usr[0]# optional => default argument
from typing import Optional
def func(output: Optional[bool] = False): # default parameter
pass# sequence => accessible by index => str, list, tuple
from typing import Sequence
def foo(seq: Sequence) -> None:
pass
foo([1, 2, 3])
foo((1, 2, 3))
foo("Hello") # tuple => needs to define data type for each tuple element
from typing import Tuple
tpl: Tuple[int, int, int] = (1, 2, 3)# callable => for a method
from typing import Callable
def add(a: int, b: int) -> int:
return a + b
def double(func: Callable[[int, int], int]) -> int:
return func(10, 20) * 2
double(add)# lambda
from typing import Callable
add_two_nums: Callable[[int, int], int] = lambda x, y: x + y# TypeVar => Generic => To preserve/maintain same input/output data type
from typing import TypeVar
T = TypeVar('T')
def front(lst: List[T]) -> T:
return lst[0] / 2 # Incompatible return value type (got "float", expected "T")
# since T(int) changed to T(float) after divided by 2
def front(lst: List[T]) -> T:
return lst[0] # It should be good since T isn't changed here
front([10, 20, 30])More Info => https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html ⬆ back to top
| Directive | Example | Directive | Example |
|---|---|---|---|
%a |
Sun | %A |
Sunday |
%d |
01 (day) | %m |
01 (month) |
%b |
Jan | %B |
January |
%y |
13 (year) | %Y |
2013 (year) |
%H |
13 (24 hour) | %I |
1 (12 hour) |
%p |
AM, PM | %Z |
EST, PST |
%M |
59 (minutes) | %S |
45 (seconds) |
from datetime import datetime
import time
dt1 = datetime(2010, 1, 2) # 2010-01-02 00:00:00 (datetime object for specific date)
dt2 = datetime.now() # 2022-11-11 20:35:15.133546 (datetime object for now)
dt = datetime.fromtimestamp(time.time()) # 2022-11-11 20:35:15.133547 (create datetime obj from timestamp)
print(dt) # 2022-11-11 20:44:14.250334
print(f"{dt.month}/{dt.day}/{dt.year}") # 11/11/2022
print(dt2 > dt1) # True# convert a string into datetime object
dt = datetime.strptime("2018-01-21", "%Y-%m-%d") # 2018-01-21 00:00:00
# convert a datetime obj into string
year_month = dt.strftime("%Y-%m") # 2018-01 # timedelta
from datetime import datetime, timedelta
dt1 = datetime(2010, 1, 2) + timedelta(days=3) # 2010-01-05 00:00:00
dt2 = datetime.now() # 2022-11-11 20:56:34.348977
print(dt1)
print(dt2)
td = dt2 - dt1 # datetime - datetime => timedelta
print(td) # 4693 days, 20:56:34.348977
print(td.days) # 4693
print(td.seconds) # 75394
print(td.total_seconds()) # 405550594.348977import random
random.random() # 0.6709288725924469 (generate randomly floating number)
random.randint(100, 110) # 105 (random number from a range)
# randomly picks a value from a sequential
random.choice([21, 43, 65, 76]) # 43
# randomly picks more than one value based on 'k'
random.choices([21, 43, 65, 76], k=3) # [65, 43, 65]
nums = [1, 2, 3, 4, 5]
random.shuffle(nums) # changed the order randomly
print(nums) # [5, 1, 2, 4, 3]# a good example
import string, random
combined_string = string.ascii_letters + string.digits + string.punctuation
print(combined_string)
# abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
strong_password = "".join(random.choices(combined_string, k=8))
print(strong_password) # WA3k*?D5
print(strong_password) # R?BGDNj<from faker import Faker
fake = Faker('en-US') # faker obj for English
fake = Faker()
fake.name() # Richard Guzman
fake.unique.name() # Nancy Hurst (Every names should be unique Once create multiplas within single shot)
fake.first_name() # Tammy
fake.last_name() # Barnes
fake.email() # daltonreyes@example.org
fake.safe_email() # michaelhess@example.org
fake.phone_number() # (122)127-6210x4172
fake.image_url() # https://placeimg.com/614/408/any
fake.ssn() # 781-02-4026
fake.address() # 78917 Jon Suite 271 Port Duaneview, HI 40684
fake.city() # South Karenchester
fake.zipcode() # 20893
fake.country() # Norwayfake.bothify("???-###", letters="MAXI") # XIX-218 (? => letters, # => digits)
fake.random_int(min=10, max=20) # 16
fake.csv() # "Rodney Castaneda","869 Port Christopherland, KS 76525"
fake.json() # [{"name": "Joseph Smith", "residency": "930 Madison Extension, OH 93947"}]
fake.date() # 1981-05-02
fake.past_date() # 2022-10-22
fake.future_date() # 2022-11-21from faker import Faker
from faker.providers import BaseProvider
from faker.providers import DynamicProvider
fake = Faker()
class MyProvider(BaseProvider):
def age(self) -> int:
return fake.random_int(min=0, max=100)
# add new provider to faker instance
fake.add_provider(MyProvider)
print(fake.age()) # 41
# or without following class
test_status = DynamicProvider(
provider_name="test_status",
elements=["Passed", "Failed", "Skipped"],
)
fake.add_provider(test_status)
print(fake.test_status()) # Failed (randomly picks one like random.choice())@dataclass is one of the best practice, if our class is data based or data focused. It automitacally creates the init, repr, eq method for a class. no need to explicitly create those those method.
- default behaviour:
@dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) - if you want do comparison like
__gt__, __ge__, __lt__, __le__, then you've to make the order as True. ex:@dataclass(order=True) - by default dataclasss' properties are mutable, we can change/set the property's value. if you want to make it immutable, then frozen should be True. ex:
@dataclass(frozen=True) - unsafa_hash control the hash value. by default it's false. if you want to generate the hash value of your dataclass object, then you've to make the unsafe_hash as True. ex:
@dataclass(unsafe_hash=True) - inside dataclass if we create property with type, those property automitacally goes into
__init__method as instance propery not class property. __post_init__as name says, it can easily access the properties of__init__method or whatever propery created inside dataclass with type. Auto generated__init__()method of dataclass automitacally calls the__post_init__(), if it is exist inside dataclass.__post_init__method is triggered Once__init__()is done.- field: field helps to change the default behavior dataclass property. ex:
from dataclasses import dataclass, field
obj.__dataclass_fields__ # to see all the fields of dataclass
obj.__dataclass_fields__['age'] # to see specific field
@dataclass
class Investor:
name: str
age: int
cash: float field(repr=False, campare=True, default=10.0)
@dataclass
class Person:
name: str
city: str
age: int
is_senior_citizen: bool = field(init=False)
def __post_init__(self):
if age > 60:
is_senior_citizen=True
else:
is_senior_citizen=FalseDataClass Inheritance: if you property are common between Parent class & Child class. The parent class propery should be replaced by child class property.
@dataclass
class Person:
name: str
city: str
age: int
@dataclass
class Student(Person)
std_id: int
std_email: str
s = Student("John", "Brooklyn", 25, "1001", "john@email.com")A Good Example
from dataclasses import dataclass
@dataclass
class Person:
name: str
email: str
age: int
country: str
def __post_init__(self):
for key, val in self.__dict__.items():
if key != 'age':
setattr(self, key, val.upper())
_dataclass = Person(*['John', 'john@gmail.com', 30, 'USA'])
_dataclass # Person(name='JOHN', email='JOHN@GMAIL.COM', age=30, country='USA')and
from dataclasses import make_dataclass
def get_data():
tpl_list = [('name', str), ('email', str), ('age', int), ('country', str)]
return make_dataclass('Person',
tpl_list,
namespace={
'__post_init__': lambda self: [setattr(self, k, v.upper()) for k, v in self.__dict__.items() if not (k == 'age')]
})
person_data = ['John Doe', 'john@gmail.com', 30, 'USA']
_dataclass = get_data()
data_elements = _dataclass(*[dt for dt in person_data])
data_elements # Person(name='JOHN DOE', email='JOHN@GMAIL.COM', age=30, country='USA')After python 3.7, python dictionary is able to maintain insertion order like OrderedDict. So, now you can maintain insertion order using python dictionary. OrderedDict has some extra feature though
from collections import OrderedDict
std_ids = [("john", "342"), ("joe", "654"), ("max", "976"), ("mike", "102")]
# can pass iterator obj as argument
ord_dict = OrderedDict(std_ids)
# OrderedDict([('john', '342'), ('joe', '654'), ('max', '976'), ('mike', '102')])
ord_dict.move_to_end('john')
# OrderedDict([('joe', '654'), ('max', '976'), ('mike', '102'), ('john', '342')])
ord_dict.popitem()
# OrderedDict([('joe', '654'), ('max', '976'), ('mike', '102')])It's bahaving like a tuple (Immutable) but it's more readable and optimized.
from collections import namedtuple
# normal tpl
admin = ('admin', 'password')
admin[0] # admin
# namedtuple
User = namedtuple('User', ['username', 'password'])
admin = User("admin", "******")
editor = User(username="editor", password="******")
admin.username # admin
editor.username # editorwe can get same readability by using dictionary but it's more verbose. everytime to create a new user we need to use keys but in namedtuple it's optional. if we want we can use keys or we can skip it. and in python dictionary we can't access the value by using . syntax.
from collections import namedtuple
# namedtuple
User = namedtuple('User', ['username', 'password'])
admin = User("admin", "******")
editor = User(username="editor", password="******")
admin.username # admin
editor.username # editor
# dictionary
admin = {"username": "admin", "password": "******"}
editor = {"username": "editor", "password": "******"}
admin['username'] # admin

