# Python Basics

### built-in types

``````#boolean
print(True==1)  # True
print(False==0)  # True
print(True==2)  # False
print(False==2)  # False
#numeric int,float,complex
f=1.5#float
i=12#int
c=3+4j#complex
#sequence list,tuple,range,bytes,str
str_t="hello"
bytes_t=b"bytes"
list_t=[1,2,3]
tuple_t=(1,2,3,4)

#set and dect
set_t={3,2,3,1,4}
dect_t={"a":3,1:4}

``````

Numerical Operations

``````from decimal import Decimal
from fractions import Fraction
#math for real numbers, cmath for complex numbers
import math, cmath

#fractions
f=Fraction(0.54)
print(f.numerator, f.denominator)#607985949695017 1125899906842624
f=Fraction(0.54).limit_denominator(1000)
print(f.numerator, f.denominator)#27 50
f=Fraction("22/7")
print(f.numerator, f.denominator)#22 7
# converting to float
print(float(f))#3.142857142857143
# converting to int
print(int(f))#3

#complex numbers
a=67j#complex number complex(0,67)
##converting to polar form
r=abs(a)#67

#decimal
d=Decimal("0.54")
print(d)#0.54

#rounding
print(round(0.54,1))#0.5
print(round(0.54,0))#1.0
#floor and ceil
print(math.floor(0.54))#0
print(math.ceil(0.54))#1

#operations
print(0.54+0.46)#1.0
print(0.54-0.46)#0.08
print(0.54*0.46)#0.2484
print(0.54/0.46)#1.173913043478261
print(0.54//0.46)#1.0
print(round(0.54%0.46,3))#0.08
print(0.54**0.46)#0.7913832183656556

(19/155)*(155/19) #0.9999999999999999
round((19/155)*(155/19)) #1
(19/155)*(155/19) == 1.0#False
math.isclose((19/155)*(155/19), 1)#True

value= 0x110 #0b10001000

import random
rand_val = random.randint(1, 100)
print(random.randrange(0, 100, 5))# 0, 5, 10...95
print(random.randint(1, 100))# 1, 2, 3...100
``````

string

In Python, single-quoted strings and double-quoted strings are the same. This PEP does not make a recommendation for this. Pick a rule and stick to it. When a string contains single or double quote characters, however, use the other one to avoid backslashes in the string

``````#single line
m:str="hello world"
#multi lines
m2:str="""hello world
my name is python"""

m_digit:str="124"
print(m_digit.isnumeric())# True
print(m_digit.isalpha())# False

``````

regular expressions

``````import re

string:str = 'hello 12 hi 89. Howdy 34'
regex:re= re.compile(r'(\d+)')
result = regex.findall(string)#['12', '89', '34']

regex2:re= re.compile(r'(\d+) hi')
result=regex2.search(string)
print(result.group(0),result.start(0),result.end(0))#12 hi 6 11
print(result.group(1),result.start(1),result.end(1))#12 6 8

string:str = 'hello 12 hi 89. Howdy 34'
result = re.sub(r'\d+', '', string)# remove all digits``````

formatted strings

``````f'{id:s}  : {location:s} : {max_temp:d} / {min_temp:d} / {precipitation:f}'
f'{id:3d}  : {location:19s} : {max_temp:3d} / {min_temp:3d} / {precipitation:5.2f}' #'IAD  : Dulles Intl Airport :   32 /  13 /  0.40'

value= 42
string:str = f'{value} {2**7+1}'# 42 129
string:str = f'{value=} {2**7+1=}'# value=42 2**7+1=129

string:str = f'{value:b} {0.2:2.0%}'# 10001000 20%

m="hello %s %s %s" % ("world", "!" , 1)``````

string module

``````import string
value="Hello, World!"
print(value.translate(str.maketrans('','',string.punctuation+string.whitespace)))#HelloWorld``````

single byte sequence b’hello world’

``````value="محمد العبدلي"
print(len(value.encode('utf-8', 'ignore')))#23
``````

## Tuples

``````m:tuple =(1,23,4,5,6,7,5,9,10)
if(m.__class__==tuple):
print("True")
print(len(m))#9
print(m.count(5))#2
print(m.index(5))#3

v1,v2,v3,v4,v5,v6,v7,v8,v9 = m
print(v1,v2,v3,v4,v5,v6,v7,v8,v9)#1 23 4 5 6 7 5 9 10``````

## Handling Exceptions

``````def sum_n(n: int) -> int:
if(n < 0):
raise Exception("n must be a positive integer")
s = 0
for i in range(1, n+1):
s += i
return s

try:
total=sum_n(-1)
print(total)
except Exception as e:
print(e)``````
``````     try:
target = shutil.copy(source_path, target_path)
except FileNotFoundError:
try:
target_path.parent.mkdir(exist_ok=True, parents=True)
target = shutil.copy(source_path, target_path)
except OSError as ex2:
print(f"{target_path.parent} problem: {ex2}")
except OSError as ex:
print(f"Copy {source_path} to {target_path} error {ex}")
``````

## Functions

``````def hex2rgb(hx_int):
if isinstance(hx_int, str):
if hx_int [0] == "#":
hx_int = int(hx_int [1:], 16)
else:
hx_int = int(hx_int, 16)
r, g, b = (hx_int >> 16) & 0xff, (hx_int >> 8) & 0xff, hx_int & 0xff
return r, g, b

#or

def hex2rgb(hx_int: Union[int, str]) -> Tuple[int, int, int]:
if isinstance(hx_int, str):
if hx_int[0] == "#":
hx_int = int(hx_int[1:], 16)
else:
hx_int = int(hx_int, 16)
r, g, b = (hx_int >> 16)&0xff, (hx_int >> 8)&0xff, hx_int&0xff
return r, g, b

RGB = Tuple[int, int, int]
HSL = Tuple[float, float, float]
def rgb_to_hsl(color: RGB) -> HSL:
def hsl_complement(color: HSL) -> HSL:
def hsl_to_rgb(color: HSL) -> RGB:``````
``````from typing import Union
from decimal import Decimal
number=Union[int,float,Decimal,complex]
return a+b
``````def dice_t(n: int, sides: int = 6) -> Tuple[int, ...]:
return tuple(random.randint(1, sides) for _ in range(n))``````
• `*` is used as a prefix for a special parameter that receives all the unmatched positional arguments. We often use `*args` to collect all of the positional arguments into a single parameter named `args`.
• `**` is used a prefix for a special parameter that receives all the unmatched named arguments. We often use `**kwargs` to collect the named values into a parameter named `kwargs`.
• `*`, when used by itself as a separator between parameters, separates those parameters. It can be applied positionally or by keyword. The remaining parameters can only be provided by keyword.
``````def mm(*args):
print(args)
mm(1,2,3,4)#(1, 2, 3, 4)

def mm(**args):
print(args)
mm(a=1,b=2,c=3)# {'a': 1, 'b': 2, 'c': 3}

def mm(*, x, y):
return x, y
print(mm(x=1, y=2))  # (1, 2)``````

iterable function

``````def fibo_iter() -> typing.Iterable[typing.Tuple[int, int]]:
a = 1
b = 1
while True:
yield (a, b)
a, b = b, a + b

for i, f in fibo_iter():
if i >= 10:
break
print(f, end=' ')``````

recursion

``````def factorial(n: int) -> int:
if(n>0):
return factorial(n-1)*n
else:
return 1
print(factorial(5))  # 120``````

lambda

``lamb= lambda x: x**2``

#### typing module

``````v:typing.Union[int,float] = 1.0#union for merge many types in one type
print(isinstance(v,typing.Union[float,set,dict])) #true

#object is super of all classes
m = 12
print(isinstance(m,object))#true
print(issubclass(int,object))#true

callable:typing.Callable= lambda m: m+12
print(callable(12),isinstance(callable,typing.Callable))#24 true

Vector: TypeAlias = list[float]

UserId = NewType('UserId', int)
some_id = UserId(524313)``````

### Decorators

``````def decorator(func):
def wrapper(*args, **kwargs):
print(args, kwargs)
print('Before function')
func(*args, **kwargs)
print('After function')
return wrapper

@decorator
def say_hello(name):
print(f'Hello {name}')``````
``type alias``
``type tt=typing.Iterable[int]``

with keyword

``````class MyContextManager:
def __enter__(self):
print("Entering the context.")
return self

def __exit__(self, exc_type, exc_value, traceback):
print("Exiting the context.")
if exc_type:
print(f"Exception: {exc_value}")
return True  # Suppress exception

with MyContextManager():
print("Inside the context.")
raise ValueError("An error occurred!")``````
``````with open('example.txt', 'r') as file:
#----------------------