Python Practice

Python Practice

FUNCTIONS

 def say_hello():
#   print("Hello!")
#   print("Hello!")
#   print("Hello!")
#   print("Hello!")
#   print("Hello!")
#   print("Hello!")


# def say_hello():
#   print("Hey there!")
#   a = "Hello"
#   return("Whats up!")

# #return vs print
# #print displays the output
# #return saves the output so that you can use it afterwards.
# #once you use return, python thinks that the code is finished and there is no more to do. So if you use a command after returning, it will not run.


# result = say_hello()
# print(result)


# def say_goodbye():
#     print("good bye")

# say_goodbye()


# def square_of_10():
#     return 10 ** 2


# say_hello()

# say_goodbye()

# square_of_10()

# say_hello()


from random import random

from selenium.webdriver.remote.errorhandler import ErrorCode

# print(int(random() * 1000000))


def flip_coin():
    if random() > 0.5:
        return "Heads"
    else:
        return "Tails"


print(flip_coin())


def add(first, second):
    if type(first) == int and type(second) == int:
        return first + second
    else:
        return "Please enter only integers"


print(add(20, 5))


def power_to(number, power):
    return number ** power


print(power_to(50, 3))


def power_to(number, power, message):
    return f"{message} - {number ** power}"


print(power_to(50, 3))
print(power_to(50, 3, "Hello World"))
print(power_to("Hello World", 50, 3))


def filter_out(info):
    if info.lower().find("delhi") == -1:
        return "Your job request has been accepted"
    else:
        return "Sorry there was no job, it was a mistake"


user_input = input("What is your name and where are you from? ")

print(filter_out(user_input))


def sum_odd_numbers(numbers):
    total = 0
    for num in numbers:
        if num % 2 != 0:
            total += num
            return total


# print(sum_odd_numbers([1,2,3,4,5]))

# def power_to(number=5, power=2, message="The answer is"):
#     return f"{message} - {number ** power}"

# print(power_to(10, 4, "Hello"))
# print(power_to(10))
# print(power_to())


def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def divide(a, b):
    return a / b


def math(a, b, fn=add):
    return fn(a, b)


print(math(10, 120, subtract))
print(math(10, 120))


def full_name(first, last):
    return "Your name is " + first + " " + last + "."
    return f"Your name is {first} {last}."


def div(dividend, divisor):
    return dividend / divisor


print(full_name("D'Silva", "Jostin"))
print(div(2, 10))

print(div(divisor=2, dividend=10))


# Scope

result = "Hello World"


def power_to(number=5, power=2, message="The answer is"):
    dog = "Beagle"
    if number == 10:
        print(dog)
        name = "Arnold"
        print(name)
    result = f"{message} - {number ** power}"
    print(result)
    return result


print(power_to())
print(power_to(10))


num = 100


def power_to(number=5, power=2, message="The answer is"):
    global num
    num += 200
    return f"{message} - {number ** power}"


print(power_to(10))
print(num)
# built-in scope
a = 100


def outer():
    count = 0  ## non-local or global scope

    def inner():
        a = 20
        nonlocal count
        count += 1  # local scope
        return count

    return inner()


outer()

# nonlocal count
# count += 10
# print(count) # ERROR


def power_to(number=5, power=2, message="The answer is"):
    """This is a little information about this function. It will do some exponent math.
    This is my help/description about the function"""
    return f"{message} - {number ** power}"


print(power_to(10))

print(power_to.__doc__)

print(help(power_to))



def add(*nums):
    print(nums)
    print(type(nums))
    total = 0
    for num in nums:
        total += num
    return total

print(add(1,2,34,4,34,-1000,6,743,3))


def printme(*names):
    message = "Hello"
    for name in names:
        print(f"{message} {name}")

printme("Hello there",Aniket", 100, "Dinesh", True, "Rajesh", "Ashwini")

def entry(*names):
    if 'delhi' in names:
        print("You are not allowed in here")
    else:
        print("Please come in")

entry('Definite', True)
entry("delhi")
entry("Mumbai")

def profile(**details):
    print(details)

    for k,v in details.items():
        print(f"{k} - {str(v).upper()}")
    #print(f"{first_name} {last_name}")

print(profile(last_name="Wick", first_name="John", age=23, job="Software Developer"))

def show_info(a, b, *args, role="moderator", **kwargs):
    return [a, b, args, role, kwargs]

print(show_info(1, 2, 3, first_name="John", last_name="Wick"))

# # unpacking
def adding(*nums):
    total = 0
    for num in nums:
        total += num
    return total

list1 = [1,2,3,4]


print(add(*list1))

def say_name(first, last):
    print(f"My name is {first} {last}.")

name = {"first": "Don", "last_name": "Corleone"}

dict1 = {"first": "Lucifer", "last":"Morningstar"}
say_name(**dict1)
say_name(first="Don", last="Corleone")

def say_name2(**names):
    for k,v in names.items():
        print(f"My {k} is {v}")

say_name2(first="Don", last_name="Corleone", profession="Mafia")

def square(a):
    return a * a

print(square(10))

squared = lambda a,b: a * a * b
print(squared(20,10))
print(type(squared))

squared = 10
print(squared)
print(type(squared))


def math(a,b,fn):
    return fn(a,b)


def add(a,b):
    return a + b

print(math(10,20,add))

print(math(1200,2,lambda a,b: a * b))
print(math(200,12,lambda a,b: a * b + (a ** 2)))

nums = [1,2,3,4,5,6,7,8]

triples = list(map(lambda num: num ** 3, nums)) # map object
# quads = [num**4 for num in nums]
print(triples)
mul5 = [num * 5 for num in triples]
print(mul5)
print(dict(triples))
# print(list(triples))
# print(list(triples))
# print(quads)
names = ["Gordon Gecko", "Definite", "Will Smith", "Willis", "SSR", "Harvey Spectre", "Amir Khan", "Vijay Chauhan", "Bruce Wayne"]
filtered_list = list(filter(lambda name: name[0].lower() == 'w', names))
print(filtered_list)


def manipulate_list(list, command, location, value=None):
    if command == "add" and location == "end":
        if value:
            list.append(value)
            print(list)
        else:
            print("Please provide a value")
    elif command == "add" and location == "front":
        if value:
            list.insert(0, value)
            print(list)
        else:
            print("Please provide a value")
    elif command == "remove" and location == "end":
        if not value:
            list.pop()
            print(list)
        elif value != list[-1]:
            print(f"{value} is not the last value in the list")
            print(list)
        else:
            list.pop()
            print(list)
    elif command == "remove" and location == "front":
        if not value:
            list.pop(0)
            print(list)
        elif value != list[0]:
            print(f"{value} is not the first value in the list")
            print(list)
        else:
            list.pop(0)
            print(list)

my_list = [1, 2, 3, 4, 5]
manipulate_list(my_list, "add", "end", 100)
manipulate_list(my_list, "add", "front", 50)
manipulate_list(my_list, "remove", "end", 50)
manipulate_list(my_list, "remove", "front", 50)
manipulate_list(my_list, "remove", "end")
manipulate_list(my_list, "add", "end")

# Ex. 9


def is_palindrome(str):
    return str.lower() == str.lower()[::-1]


print(is_palindrome("anna"))


# Filter and map -> console output
nums = [1,2,3,4,5]
# >>>
mapped = map(lambda num: num + (num * 2), nums)
# >>>
print(mapped)
# <map object at 0x00000154D7637FA0>
list(10)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: 'int' object is not iterable
>>> list("hello")
# ['h', 'e', 'l', 'l', 'o']
>>> list(mapped)
# [3, 6, 9, 12, 15]
>>> mapped = list(map(lambda num: num + (num * 2), nums))
>>> mapped
# [3, 6, 9, 12, 15]
# >>>
# >>>
>>> nums
# [1, 2, 3, 4, 5]
# >>>
# >>>
>>> filtered = list(filter(lambda num: num % 2 != 0, nums))
>>> filtered
# [1, 3, 5]
# >>>
>>> category = ["apple", "samsung", "lenovo", "hp", "dell", "asus"]
# >>>
>>> filtered = filter(lambda cat: cat == "apple", category)
# >>>
>>> list(filtered)
# ['apple']
# >>>
>>> user = ["apple", "Karbonn"]
# >>>
>>> filtered = filter(lambda cat: cat in user, category)
# >>>
>>> list(filtered)
# ['apple']
# >>>


names = ["John", "Jack", "James", "Desmond", "Charlie", "Jacob"]

survived = list(
    map(lambda name: f"Winner: {name}", list(filter(lambda name: len(name) < 5, names)))
)

print(survived)

names = ["John", "Jack", "James", "Desmond", "Charlie", "Jacob"]
print(all(names))

print(all([name[0] == "J" for name in names]))
print([name[0] == "J" for name in names])


print(any(name for name in names if len(name) > 3))


nums = (123, 123, 21314, 5, 643, 2, 23321, 1)

print(sorted(nums, reverse=True))


>>> sorted("Hello")
# ['H', 'e', 'l', 'l', 'o']
>>> sorted("Hello2324")
# ['2', '2', '3', '4', 'H', 'e', 'l', 'l', 'o']
>>> sorted("Hello2324JAS")
# ['2', '2', '3', '4', 'A', 'H', 'J', 'S', 'e', 'l', 'l', 'o']
>>> sorted([12,234,4,5,6])
# [4, 5, 6, 12, 234]
>>> tuple(sorted([12,234,4,5,6]))
# (4, 5, 6, 12, 234)
>>> tuple(sorted([12,234,4,5,6,6,6]))
# (4, 5, 6, 6, 6, 12, 234)
>>> set(sorted([12,234,4,5,6,6,6]))
# {4, 5, 6, 234, 12}
>>> sorted(set(sorted([12,234,4,5,6,6,6])))
# [4, 5, 6, 12, 234]
# >>>

# # Sidenote - generators
import sys

print(sys.getsizeof([1123213, 213, 213, 213, 21, 321, 3, 213, 213, 21, 3]))

lst = [num * 10000 for num in range(0, 1000)]
gen = (num * 10000 for num in range(0, 1000))

print(sys.getsizeof(lst))
print(sys.getsizeof(gen))


>>> reversed("hello")
# <reversed object at 0x000002304493A550>
# >>>
>>> list(reversed("hello"))
# ['o', 'l', 'l', 'e', 'h']
# >>>
# >>>
>>> "".join(reversed("hello"))
# 'olleh'
# >>>
# >>>
>>> abs(-33.3333)
# 33.3333
>>> abs(-33.3)
# 33.3
>>> abs(0)
# 0
>>> abs(-0)
# 0
# >>>
# >>>
# >>>
>>> sum([1,2,3])
# 6
>>> sum([1,2,3,-4])
# 2
>>> sum([1,2,3])
# 6
>>> sum([1,2,3], 100)
# 106
>>> sum([1,2,3], 5)
# 11
>>> sum(range(1, 21), 5)
# 215
>>> sum(range(1, 21), 1000)
# 1210
# >>>
# >>>
# >>>
>>> round(99.99)
# 100
>>> round(99.94)
# 100
>>> round(99.49)

ages = [23, 4, 532, 23, 45, 21, 98]
names = [
    "Hitler",
    "Elon Musk",
    "Warren Buffet",
    "Kim Jon Un",
    "Nikola Tesla",
]
birth_place = ["Austria", "South Africa", "New York", "North Korea", "USA"]

print(list(zip(names, ages, birth_place)))

ERROR HANDLING

try:
    # attempt
    num = int(input("Please enter a number: "))
except TypeError:
    # if unsuccessful
    print("That's not a number!")
else:
    # if successful
    print(num * 100)
finally:
    # runs either way (in the end). Whether success or error
    print("Runs no matter what!")


Write a function called inc_dec_list which accepts a list of numbers
and a command. If the command is "increase" then then add 1 to all
the numbers in the list and return that list. If the command is
"decrease" then subtract 1 instead. Use the map function to achieve this.


def inc_dec_list(num_list, command):
    if command == "increase":
        return list(map(lambda n: n + 1, num_list))
    elif command == "decrease":
        return list(map(lambda n: n - 1, num_list))
    else:
        return "Unknown Command"


print(inc_dec_list([10, 20, 30, 40, 50], "increment"))


num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

result = list(filter(lambda n: n < 7, num_list))

print(num_list)
print(result)


names = ["John", "Jack", "James", "Desmond", "Charlie", "Jacob"]
survived = list(
    map(lambda name: f"Winner: {name}", list(filter(lambda name: len(name) < 5, names)))
)
print(survived)

Some more data type practice

my_mixed_list = [23, True, "Hello", "mumbai", "delhi", "This is a very long string"]

print(my_mixed_list)
# # Ctrl /

for item in my_mixed_list:
    print(item)

# Exercise 1
# ...

my_dict = {"city1": ["mumbai", "kurla"], "city2": "delhi", "something_else": 2345}

print(my_dict["city2"])
print(my_dict["city1"])

print(my_dict["something_else"])


for key, value in my_dict.items():
    print(f"My {key} is {value}")


for value in my_dict.values():
    print(f"My value is {value}")

for key in my_dict.keys():
    print(f"My key is {key}")


def cool(num1, num2):
    return f"this is {num1} and this is {num2}"


def notcool(num1, num2):
    return num1 * num2


def my_func(number1, number2, number3):
    return number1 + number2 + number3


print(my_func(10, 20, -100))


def my_func2(number1, number2, func):
    return func(number1, number2)


print(my_func2(10, 20, cool))
print(my_func2(10, 20, notcool))


def coolman(*args):
    print(args)

    for item in args:
        print(item)


coolman("this", "that", "cricket")


def add(*nums):
    total = 0
    print(type(nums))

    for num in nums:
        total += num
        total = total + num

    return total


print(add(10, 20, 3, 4, 6, 89, 100))

MODULE

import random

print(random.random() * 100)
print(random.randint(10, 100))

# def random():
#     # code

# # import random

import random as cool

names = ["Donald Trump", "Kanye West", "Amir Khan", "Dubai", "Kurla"]

value = random.choice(["Donald Trump", "Kanye West", "Amir Khan"])
value = cool.choice(["Donald Trump", "Kanye West", "Amir Khan"])

print(names)
random.shuffle(names)
cool.shuffle(names)
print(names)
print(value)


# from random import randint as koi_number, choice as pasand, shuffle
from random import *

# print(randint(0, 10))
# print(koi_number(0, 50))
# print(pasand([1, 2, 3, 4, 5]))


print(randint(10, 100))
print(random())
print(choice(["first", "second"]))

Object Oriented Programming

class Human:
    def __init__(self, name, race, profession, city):
        self.name = name
        self.race = race
        self.profession = profession
        self.city = city
    def info(self):
        print(f"Name: {self.name}")
        print(f"Race: {self.race}")
        print(f"Prof: {self.profession}")
        print(f"City: {self.city}")

user1 = Human("Mojo Man", "Brown", "Python Developer", "Pune")

user2 = Human("John Brown", "Brown", "Java Developer", "Delhi")


print(user1.profession)
print(user2.city)

user1.info()
user2.info()

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

class Email:
    def __init__(self, to, cc, bcc, subject, message):
        self.to = to
        self.cc = cc
        self._bcc = bcc  # private attribute
        #self.__bcc = bcc  # Mangled attribute - _Email__bcc
        self.subject = subject
        self.message = message
        self.sender = "Gmail"

    def print_email(self):
        print(
            f"To: {self.to}\nCC: {self.cc}\nSubject: {self.subject}\nMessage: {self.message}"
        )

    # Getter method
    def get_bcc(self):
        return self._bcc

    # Setter method
    def set_bcc(self, email):
        self._bcc = email

my_email = Email(
    "john@gmail.com",
    None,
    "jack@outlook.com",
    "I am trying to install Numpy!",
    "It isn't happening.",
)

my_email2 = Email(
    "john2@gmail.com",
    "jon_snow@got.com",
    "jack2@outlook.com",
    "You know nothing",
    "Jon Snow. - Igrite",
)

print(my_email.to)
print(my_email.cc)
print(my_email.subject)
print(my_email.message)
print(my_email._Email__bcc)
print(my_email.sender)

my_email.to = "COOLMAN@COOLMAN.com"
my_email.sender = "Outlook.com"

print(my_email.to)
print(my_email.sender)

print(dir(my_email))


print(f"To: {my_email2.to}\nSubject: {my_email2.subject}")


my_email2.print_email()

print(my_email2.get_bcc()) #jack2@outlook.com
my_email2.set_bcc("hound@lannister.com")
print(my_email2.get_bcc()) #hound@lannister.com

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

class Pokemon:
    def __init__(self, name, type, **attacks):
        self.name = name
        self.type = type
        self.attacks = attacks
        self._health = 100

    # Getter method for private attribute health
    def get_health(self):
        return self._health

    def attack(self, attack_name):
        # will return a dictionary. ex: {"slash": 10}
        return {k: v for k, v in self.attacks.items() if k == attack_name}

    def damage(self, attack):
        # attack param is a dictionary. ex. {"fireball": 27}
        attack_name = list(attack.keys())[0]
        attack_hitpoints = list(attack.values())[0]
        #self._health = self._health - attack_hitpoints
        self._health -= attack_hitpoints
        print(self.name, "got hit by", attack_name, "and took a damage of",  attack_hitpoints, "%."
        )


pika = Pokemon("Pikachu", "Electric", slash=10, thundershock=25, speed=18)
char = Pokemon("Charmender", "Fire", slash=12, fireball=27, flamethrower=15, speed=5)

print(char.get_health())
pika.damage(
    char.attack("fireball")
    )

print(pika.get_health()) #73


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

# class User:
#     total_users = 0

#     def __init__(self, name, age):
#         self.name = name
#         self.age = age
#         User.total_users += 1

#     @classmethod
#     def get_total_users(cls):
#         return cls.total_users


# class Math:
#     @classmethod
#     def add(cls, a, b):
#         return a + b

#     @classmethod
#     def subtract(cls, a, b):
#         return a - b

# print(Math.add(10, 5))

# ganesh = User("Ganesh Gawde", "18")
# aniket = User("Aniket Ghume", "21")

# print(ganesh.age)
# print(aniket.age)

# print(ganesh.total_users)
# rajesh = User("Rajesh", "21")

# print(User.total_users)
# print(aniket.total_users)
# print(User.total_users)

# print(f"Class Method Result: {aniket.get_total_users()}")
# print(f"Class Method Result: {User.get_total_users()}")


-----------------------------------------------------------------------
# class User:
#     total_users = 0

#     def __init__(self, name, age):
#         self.name = name
#         self.age = age
#         User.total_users += 1

#     def __repr__(self):
#         return f"Name: {self.name}\nAge: {self.age}"

#     @classmethod
#     def get_total_users(cls):
#         return cls.total_users


# naaz = User("Naaz", 25)

# print(naaz)

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




# class User:
#     # constructor
#     def __init__(self, name, email):
#         self.name = name
#         self.__email = email  # __ - name mangling. _User__email

# john = User("John", "john@gmail.com")

# print(john.name)  # "John"
# print(john._User__email)  # "john@gmail.com"


--------------------------------------------------------------
# # Inheritance


# # Base class
# class User:
#     # constructor
#     def __init__(self, name, email):
#         self.name = name
#         self.email = email

#     def login(self):
#         return f"{self.name} has logged in"


# # Admin inherits from User
# class Admin(User):
#     def __init__(self, name, email, password):
#         self.name = name
#         self.email = email
#         self.password = password

#     def delete_user(self):
#         return f"You deleted a user"


# # # class Moderator(User):
# # #     pass

# # prat = User("Prat", "prat666@gmail.com")
# # vaibhav = Admin("Vaibhav", "coolzvaib@gmail.com", "1234")


# # print(prat.name)
# # print(prat.email)
# # print(vaibhav.name, vaibhav.password)

# # print(prat.login())
# # print(vaibhav.login())
# # print(prat.delete_user())
# # # print(prat.password)


# # ------------------------------


# class User:
#     def __init__(self, name, email):
#         self.name = name
#         self.email = email

#     def login(self):
#         return f"{self.name} has logged in"

# class Admin(User):
#     def __init__(self, name, email, password):
#         super().__init__(name, email)
#         # User.__init__(self, name, email)
#         # self.name = name
#         # self.email = email
#         self._password = password
#         print("I AM THE BASE!")

#     def get_password(self):
#          return self._password

#     def set_password(self, new_password):
#          self._password = new_password

#     @property
#     def password(self):
#         return self._password

#     @password.setter
#     def password(self, new_pass):
#         self._password = new_pass

# john = Admin("John Abraham", "john@dhoom.com", "bipashayabusa")

# print(john.get_password())
# john.name = "jane"

# john.set_password("northeastfc")
# print(john.get_password())

# print(f"New Name: {john.name}")
# print(john.name)

# print(john.password)
# john.password = "coolman198"
# print(john.password)


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

from colorama import init, Fore, Back, Style
from termcolor import colored
from colorama.initialise import colorama_text

# I have to to run this first.
init()


class User:
    total_users = []
    active_users = 0

    @classmethod
    def display_active_users(cls):
        print(f"There are currently {cls.active_users} users online.")

    @classmethod
    def display_total_users(cls):
        print(f"Total Users: {len(cls.total_users)}")
        idx = 0
        while idx < len(cls.total_users):
            print(f"No. {idx + 1}: {cls.total_users[idx]}")
            idx += 1

    def __init__(self, username, email, password, dob):
        self.username = username
        self.email = email
        self._password = password
        self._dob = dob
        User.total_users.append(email)

    def get_age(self):
        age = 2021 - int(self._dob.split("/")[2])
        print(f"{self.username} is {age} years old.")

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, new_password):
        self._password = new_password
        print("Your password has been updated")

    def login(self):
        if self.email in User.total_users:
            User.active_users += 1
            if isinstance(self, Moderator):
                print(colored(f"{self.username} just logged in.", "yellow"))
            else:
                print(f"{self.username} just logged in.")
        else:
            print(
                colored(
                    f"Access forbidden! {self.username} has been kicked out.", "red"
                )
            )

    def logout(self):
        User.active_users -= 1
        print(f"{self.username} has logged out.")


class Moderator(User):
    total_mods = 0

    def __init__(self, username, email, password, dob):
        super().__init__(username, email, password, dob)
        Moderator.total_mods += 1

    def delete_user(self, email):
        email_idx = User.total_users.index(email)
        User.total_users.pop(email_idx)


abhijeet = User("abhi777", "abhijeet777@gmail.com", "kadam32", "24/01/1995")
mitalee = User("mitaleeCool", "mitalee@gmail.com", "mitalee789", "06/05/1998")
pravin = User("pravin001", "pravinman@gmail.com", "pravin@123", "05/03/1998")
nikhilesh = Moderator("NikhileshMod", "iamcool@gmail.com", "nikmod51", "10/01/1999")
shweta = Moderator("shwetaMod", "shweta999@hotmail.com", "Sane888", "11/09/2001")
aadil = User("aadilcoolman", "aadil@gmail.com", "aAdIl007", "12/09/1999")

User.display_total_users()
abhijeet.login()
mitalee.login()
print(isinstance(pravin, User))
print(isinstance(nikhilesh, Moderator))
print(
    isinstance(nikhilesh, User)
)  # true, because moderator inherits from user. So nikhilesh is both
pravin.login()
abhijeet.get_age()
# mitalee.delete_user("mitalee@gmail.com")
shweta.login()
User.display_total_users()
print(User.total_users)
User.display_total_users()
nikhilesh.get_age()
shweta.password = "askjdnu632"
print(shweta.password)
User.display_active_users()
aadil.login()
User.display_active_users()
aadil.logout()
User.display_active_users()



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


from datetime import datetime
from tabulate import tabulate


class List:
    active = []
    completed = []

    @classmethod
    def add_task(cls, todo_item):
        if todo_item.status != "completed":
            cls.active.append(todo_item)
        else:
            cls.completed.append(todo_item)

    @classmethod
    def list_tasks(cls):
        # [print(todo.task) for todo in cls.active]
        print(tabulate([todo.task for todo in cls.active]))

    @staticmethod
    def yo_man(x):
        print("yo man", x)


class Todo:
    status_types = ("current", "in_progress", "in_review", "completed")

    def __init__(self, task, project=None, due_date=None, status="current", *tags):
        self.task = task
        self.project = project
        self.due_date = due_date
        self.tags = list(tags)
        self._created_at = str(datetime.now())  # private attribute
        if status not in Todo.status_types:
            return f"Invalid status. Please enter any one from the following: 'current', 'in_progress', 'in_review', 'completed'."
        else:
            self.status = status
        List.add_task(self)


todo1 = Todo("Test this application")
todo2 = Todo("This is a simple task")

List.list_tasks()

# static method, doesnt care about the class and its working or its attributes of functions, works independently
List.yo_man("pravin")



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

from random import choice
from copy import copy


class Animal:
    names = ["Walter", "Jesse", "Lisa", "Jenny", "Don", "Joe", "Jack", "Lee"]

    def __init__(self, name, type, breed, sound):
        self.name = name
        self.type = type
        self.breed = breed
        self.sound = sound

    def __repr__(self):
        return f"\nName: {self.name}\nType: {self.type}\nBreed: {self.breed}\nSound: {self.sound}\n"

    def __add__(self, other):
        if self.type != other.type:
            raise TypeError(
                f"A {self.type} and a {other.type} can't mate you sick freak!"
            )
        else:
            print(f"{self.name} is mating with {other.name} *********")
            species = type(self)
            new_breed = choice([self.breed, other.breed])
            offspring = species(choice(Animal.names), new_breed)
            print(f"Child Born:\n{offspring}")
            return offspring

    def __len__(self):
        return 100  # you have to return an integer if you want to overwrite this magic method

    def __gt__(self, other):
        if self.type == "Dog" and other.type == "Fish":
            return True
        else:
            return False

    def __mul__(self, other):
        if isinstance(other, int):
            return [copy(self) for i in range(other)]

    def make_sound(self):
        print(self.sound * 10)


class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Dog", breed, "bark")

    def make_sound(self):
        print(
            f"{self.sound * 2} Human, my name is {self.name} and I am a Daoug. {self.sound * 3}"
        )


class Fish(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Fish", breed, "splash")



tiger = Animal("Kaalu", "wild", "Jungle", "Roar")
lab = Dog("Bucky", "Labrador")
lab2 = Dog("Emily", "Labrador")
new_dog = Dog("Jack", "German Shepard")
shark = Fish("Matt", "Great White")
print(new_dog)
lab.make_sound()
shark.make_sound()
shark + new_dog  # TypeError
lab + lab2
child = lab + lab2 + new_dog
print(child.make_sound())
print(f"{child.make_sound()} is barking!")
print(lab + shark)
print(len(lab2))
print(lab > shark)
print(lab2 > lab)
dog_clones = lab * 5
# # We get back a new list of cloned dogs
print(dog_clones)
print(dog_clones[0] is dog_clones[1])  # they are different objects in memory

Generators

# name = "Khula Saand"
# name_iterator = iter(name)
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))
# print(next(name_iterator))


# # # Custom for loop
# def custom_for(iterable):
#     iterator = iter(iterable)

#     while True:
#         try:
#             print(next(iterator))
#         except StopIteration:
#             break


# # # Custom map function
# def custom_map(function, iterable):
#     iterator = iter(iterable)

#     while True:
#         try:
#             i = next(iterator)
#         except StopIteration:
#             break
#         else:
#             function(i)


# custom_for([1234, 124, 234, 1, 12, 21, 43])
# newVar = []
# custom_map(lambda x: newVar.append(x * 10), "hello")
# print("".join(newVar))


# # # Custom iterable (range function clone)
# class Counter:
#     def __init__(self, start=None, end=None, step=1):
#         if start == None:
#             self.current = 0
#             self.end = end
#         elif end == None:
#             self.current = 0
#             self.end = start
#         else:
#             self.current = start
#             self.end = end
#         self.step = step

#     #     # This is needed
#     def __iter__(self):
#         # so what this returns is what the iter() function will return
#         # This needs to be an iterator and not something stupid
#         # return iter("hello") # this will work, as it is an iterable
#         return (
#             self  # won't work without the below __next__ as it is not an iterator yet
#         )

#     # what we need is begin with `start` and keep going to `end`
#     def __next__(self):
#         if self.current >= self.end:
#             num = self.current
#             self.current += self.step
#             return num
#         elif self.current <= self.end:
#             num = self.current
#             self.current -= self.step
#             return num
#         else:
#             raise StopIteration


# c = Counter(10, 20)
# iter(c)
# d = Counter(10, 0)
# for x in Counter(0, 10, 2):
#     print(x)

# for x in Counter(10, 0, -2):
#     print(x)


# # Generator
# def count_up_to(max):
#     count = 1
#     while count <= max:
#         yield count
#         count += 1


# counter = count_up_to(10)
# print([num for num in count_up_to(12)])


# def gen_counter(start, end, step=1):
#     while start < end:
#         yield start
#         start += step


# def gen_counter(start, end):
#     while start < end:
#         yield start
#         start += 1


# c = gen_counter(1, 10)
# print(help(c))  # show this
# print(c)
# print(list(c))  # show this as well


# print(next(c))
# print(next(c))
# print(next(c))
# print(next(c))
# print(next(c))
# print(next(c))
# print(next(c))

# for num in gen_counter(1, 10):
#     print(num)


def week():
    days = [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday",
    ]
    for day in days:
        a = yield day
        print(a)


week()

Generator Expressions

# # Generator expression

# generated_nums = list((num for num in range(1000)))

# print(generated_nums)


# from sys import getsizeof

# nums_gen = (num ** 100 for num in range(10000000))
# print(f"Using a generator: {getsizeof(nums_gen)}")

# nums_list = sum([num ** 100 for num in range(10000000)])
# print(f"Using list comp: {getsizeof(nums_list)}")

# # 0, 1


# def fib_list(max):
#     nums = []
#     a, b = 0, 1
#     while len(nums) < max:
#         nums.append(b)
#         a, b = b, a + b
# return nums


# for num in fib_list(1000000):
#    print(num)


# def fib_gen(max):
#     a, b = 0, 1
#     count = 0
#     while count < max:
#         a, b = b, a + b
#         yield a
#         count += 1


# for num in fib_gen(1000000):
#     print(num)


# def add(a, b):
#     return a + b


# def sub(a, b):
#     return a - b


# # HOF
# def math(a, b, fn):
#     return fn(a, b)


# print(math(10, 20, sub))


# def sum(n, func):
#     total = 0
#     for num in range(1, n + 1):
#         total += func(num)
#     return total


# def square(n):
#     return n * n

# def cube(n):
#     return n * n * n

# print(sum(3, square))
# print(sum(3, cube))

import random


def greet(person):
    def get_mood():
        mood = ["Hey", "What!", "What the heck do you want!", "Get lost!"]
        msg = random.choice(mood)  # import random
        return msg

    result = f"{get_mood()} {person}"
    return result


print(greet("Salman"))


# function generator
def make_greet_func(person):  # closure
    def make_message():
        msg = random.choice(
            ["Hello", "What!", "What the heck do you want!", "Get lost!"]
        )
        return f"{msg} {person}"

    return make_message


greet_aditi = make_greet_func("Aditi")

print(greet_aditi())
print(greet_aditi())
print(greet_aditi())
print(greet_aditi())

Higher Order Functions

def stars(fn):
    def wrapper():
        print("*" * 10)
        fn()
        print("*" * 10)

    return wrapper


def say_hello():
    print("Hello World")


say_hello()

new_hello = stars(say_hello)

new_hello()


# function 1


def name():
    print("Pravin")


def mountain():
    print("Himalaya is cool")


# # function 2
def greet(func):

    name()
    print("HELLO BRO!")

    # new inner function
    def wrapper():
        print("Abe saale")
        print(10 ** 4)
        func()

    return wrapper


returned_func = greet(mountain)

returned_func()

def add(a, b):
    print("Hello mojo")
    return a + b

x = add(10, 50)
print(x + 10000)

returned_func()

from random import choice

# HOF (DECORATOR)
def mood(fn):
    def wrapper():
        messages = ["Get lost!", "Hello", "Piss off", "Buy beer"]
        return f"{choice(messages)} {fn()}"

    return wrapper


@mood  # name = mood(name)
def name():
    names = ["Salman", "Pravin", "Nikhilesh", "Shweta", "Mitalee", "Aditi"]
    return choice(names)


@mood
def mountains():
    mt_names = ["Mount Abu", "Mont Blanc", "Sahara", "Pravin"]
    return choice(mt_names)


name = mood(name)

print(name())
print(mountains())


greeting = mood(name)

print(greeting())







# def add(a, b):
#     return a + b

# result = add(10,20)


# # Make uppercase decorator
# def make_upper_case(fn):
#     def wrapper(*args, **kwargs):
#         return fn(*args, **kwargs).upper()

#     return wrapper


# @make_upper_case
# def say_hello(name):
#     return f"Hello, {name}."


# @make_upper_case
# def custom_hello(msg, name):
#     return f"{msg} {name}"


# @make_upper_case
# def add(a, b, c):
#     result = a + b + c
#     return f"The result of adding {a}, {b}, {c} is {result}"


# print(add(c=50, a=10, b=1000))

# say_hello = make_upper_case(say_hello)

# print(say_hello("hello world"))  # wrapper(arg) -> HELLO, HELLO WORLD!
# print(say_hello(1000))  # wrapper(arg) -> HELLO, HELLO WORLD!

# message = custom_hello("Hey bruv", "John Doe")
# print(message)

# # def add(*args):
# #     print(args)
# #     return args[0] + args[1]
# # print(add(10))


# # import time
# from time import time


# def sum_gen(value):
#     print("Executing sum_gen")
#     start_time = time()
#     result = sum(num for num in range(value))
#     end_time = time()
#     print(f"Total time elapsed: {end_time - start_time}")
#     return result


# def sum_list(value):
#     print("Executing sum_list")
#     start_time = time()
#     result = sum([num for num in range(value)])
#     end_time = time()
#     print(f"Total time elapsed: {end_time - start_time}")
#     return result


# # Speed test decorator
# def speed_test(fn):
#     def wrapper(*args, **kwargs):
#         print(f"Executing {fn.__name__}")
#         start_time = time()
#         result = fn(*args, **kwargs)
#         end_time = time()
#         print(f"Total time elapsed: {end_time - start_time}")
#         return result

#     return wrapper


# @speed_test
# def sum_gen(value):
#     return sum(num for num in range(value))


# @speed_test
# def sum_list(value):
#     return sum([num for num in range(value)])


# @speed_test
# def greet(name):
#     return f"Hello {name}"


# print(sum_gen(1000))
# print(sum_list(1000))
# print(greet("John Doe"))


# # Limit arguments decorator
# # def limit_args(fn):
# #     def wrapper(*args, **kwargs):
# #         if len(args) <= 2 or len(args) < 5:
# #             return fn(*args, **kwargs)
# #         else:
# #             return "Either too many or too less arguments"

# #     return wrapper


# # @limit_args
# # def add(*args):
# #     return sum(args)


# # print(add(1, 23, 432, 22, 1, 1, 1, 223))
# # print(add(1, 23, 432, 22))
# # print(add(1, 1))


# Authenticate/authorize decorator
def authenticate(fn):
    def wrapper(*args, **kwargs):
        if args[0]["role"] == "admin":
            return fn(*args, **kwargs)
        else:
            return "NOT AUTHORIZED"

    return wrapper


@authenticate
def access_page(user):
    return "SECRET CONTENT"


user1 = {"name": "John Doe", "username": "john123@gmail.com", "role": "admin"}
print(access_page(user1))


# def add(*args):
# return sum(args)


# my_nums = [1, 2, 34, 5, 6, 7, 8]

# print(add(121, 3223, 1, 1, 11, 2))
# print(add(*my_nums))  # argument unpacking
# when we write *my_nums while calling the function, we basically unpack all the elements inside the my_nums list and put each element in *args tuple as a separate element. If we dont unpack by putting *, tuple will have only one element as a list.






from functools import wraps
from typing import Type


def make_upper_case(fn):
    """THIS IS THE make_upper_case high-o-func"""

    @wraps(fn)
    def wrapper(*args, **kwargs):
        """THIS IS THE WRAPPER FUNCTION"""
        return fn(*args, **kwargs).upper()

    return wrapper


@make_upper_case
def say_hello(person):
    """Says hello to whoever you want."""
    return f"Hello, {person}."


@make_upper_case
def say_whatever(person, message):
    """
    Says whatever you want to whoever you want.
    Accepts 2 arguments
    @person -> name of the person
    @message -> the message you want to convey
    """
    return f"{message}, {person}."


say_whatever = make_upper_case(say_whatever)

print(say_hello("John"))
print(say_whatever("Hey bro, wassup", "John Doe"))

print(say_hello.__doc__)
print(say_whatever.__doc__)
print(make_upper_case.__doc__)

# normal func
def add(a, b):
    return a + b


print(add(10, 20))  # 30


def math(num1, num2, fn):
    return fn(num1, num2)

def add(x, y):
    return x + y

print(math(10, 20, add))
print(math(10, 20, lambda x, y: x + y))


print(math(10, 20, lambda x, y: x + y))


def limit_args(fn):
    def wrapper(*args, **kwargs):
        if len(args) < 5 or len(args) > 10:
            return "Either too many or too few arguments"
        else:
            return fn(*args, **kwargs)

    return wrapper


@limit_args
def add(*args):
    return sum(args)


@limit_args
def print_names(*names):
    for name in names:
        print(name)


# print(add(10, 20, 12, 12, 12, 4))
# print(add(10, 20))

print(print_names("Vishal", "Ankit", "Vaibhav", "Pravin"))

def limit_args(fn):
    def wrapper(*args, **kwargs):
        if len(args) < 5 or len(args) > 10:
            return "Either too many or too few arguments"
        else:
            return fn(*args, **kwargs)

    return wrapper


def limit_args(min, max):
    def inner(fn):
        def wrapper(*args, **kwargs):
            if len(args) < min or len(args) > max:
                return "Either too many or too few arguments"
            else:
                return fn(*args, **kwargs)

        return wrapper

    return inner


@limit_args(2, 5)
def add(*args):
    return sum(args)

# Original way of doing this
limit_args = limit_args(2, 5)(add)


print(add(1, 2, 3, 4))


def enforce(*types):
    def inner(fn):
        def wrapper(*args, **kwargs):
            new_args = []
            for a, t in zip(args, types):
                try:
                    new_args.append(t(a))
                except (ValueError, TypeError):
                    return "Something went wrong"
            return fn(*new_args)

        return wrapper

    return inner


@enforce(str, int)
def announce(msg, times):
    print((msg + "\n") * times)


user_msg = input("Please enter your message: ")
user_times = input("Please enter the number of times you want to print: ")

print(announce(user_msg, user_times))

# announce("Hello World!", 10)

Regular Expressions

>>> import re
>>>
>>> dir(re)
['DEBUG', 'DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'S', 'Scanner', 'T', 'TEMPLATE', 'U', 'UNICODE', 'VERBOSE', 'X', '_MAXCACHE', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', '_alphanum', '_cache', '_cache_repl', '_compile', '_compile_repl', '_expand', '_locale', '_pattern_type', '_pickle', '_subx', 'compile', 'copy_reg', 'error', 'escape', 'findall', 'finditer', 'match', 'purge', 'search', 'split', 'sre_compile', 'sre_parse', 'sub', 'subn', 'sys', 'template']
>>>
>>>
>>>
>>>import re
>>>
>>> str1 = "rohan Python Rstforum"
>>>
>>>
>>> x = re.match('r.h..',str1)
>>>
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>>
>>>
>>> x.group()
'rohan'
>>>
>>>
>>> x = re.match('P....n',str1)
>>>
>>> x
>>>
>>>
>>> x = re.match('Python',str1)
>>>
>>> x
>>>
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>>
>>>
>>> x = re.search('Python',str1)
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>>
>>> x.group()
'Python'
>>>
>>>
>>> x = re.search('P....n',str1)
>>>
>>> x
<_sre.SRE_Match object at 0x00000000032AC7E8>
>>> x.group()
'Python'
>>>
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>>
>>>
>>>
>>> str2 = 'RRRRRRohan Python'
>>>
>>> str3 = 'RRRRRRohannnnnn Python'
>>>
>>> x = re.match('R+',str2)
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>>
>>> x.group()
>>>'RRRRR'
>>>
>>> x = re.match('R+ohan',str2)
>>> x.group()
'RRRRRRohan'
>>>
>>>
>>>
>>> str3
'RRRRRRohannnnnn Python'
>>>
>>> x = re.match('R+ohan+',str3)
>>>
>>> x.group()
'RRRRRRohannnnnn'
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>> x = re.match('.+',str1)
>>>
>>>
>>> x.group()
'rohan Python Rstforum'
>>>
>>>
>>>
>>> x = re.match('.+f',str1)
>>>
>>> x.group()
'rohan Python Rstf'
>>>
>>>
>>> x = re.match('.+o',str1)
>>>
>>> x.group()
'rohan Python Rstfo'
>>>
>>>
>>>
>>>
>>> x = re.match('.+?o',str1)
>>> x.group()
'ro'
>>>
>>>
>>>
>>>
>>> str4 = "Rohan12345!@#$!@#$ Python"
>>>
>>> x = re.match('Roha\w',str4)
>>>
>>>
>>> x.group()
'Rohan'
>>>
>>> x = re.match('Rohan\w',str4)
>>> x.group()
'Rohan1'
>>>
>>> x = re.match('Roha\d',str4)
>>>
>>> x
>>>
>>> x = re.match('Rohan12\d',str4)
>>>
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>> x.group()
'Rohan123'
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>> str5 = "rohan      Pythonn"
>>>
>>> x = re.match('rohan\sPyt',str1)
>>>
>>> x.group()
'rohan Pyt'
>>>
>>>
>>> x = re.match('rohan\sPyt',str5)
>>> x.group()
'rohan\tPyt'
>>>
>>>
>>> x = re.match('R[a-z]han',str1)
>>> x.group()
'rohan'
>>>
>>>
>>> x = re.match('R[a-e]han',str1)
>>>
>>> x
>>>
>>>
>>>
>>>
>>> str7 = "rohan@123 and amit@456 are the 2 IDS"
>>>
>>>
>>> x = re.search('[a-z]+@\d\d\d',str7)
>>> x
<_sre.SRE_Match object at 0x00000000032AC7E8>
>>>
>>> x.group()
'rohan@123'
>>>
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>> x = re.match('rohan',str1)
>>> x.group()
'rohan'
>>>
>>>
>>> x = re.match('Rohan',str1)
>>> x
>>>
>>> x = re.match('Rohan',str1,re.I)
>>>
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>>
>>> x.group()
'rohan'
>>>
>>>
>>>
>>> str7
'rohan@123 and Amit@456 are the 2 IDS'
>>>
>>> x = re.search('[a-z]+@\d\d\d',str7,re.I)
>>> x.group()
'rohan@123'
>>>
>>>
>>> x = re.findall('[a-z]+@\d\d\d',str7,re.I)
>>>
>>> x
['rohan@123', 'Amit@456']
>>>
>>>
>>>
>>>
>>> str6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'str6' is not defined
>>> str5
'rohan\tPythonn'
>>> str4
'Rohan12345!@#$!@#$ Python'
>>>
>>>
>>>
>>> str4
'Rohan12345!@#$!@#$ Python'
>>>
>>>
>>>
>>> x = re.match('rohan\d',str4)
>>> x.group()
'Rohan1'
>>>
>>> x = re.match('rohan[0-9]',str4)
>>> x.group()
'rohan1'
>>>
>>> x = re.match('rohan[1-5]',str4)
>>> x.group()
'rohan1'
>>>
>>>
>>> x = re.match('rohan[5-9]',str4)
>>> x
>>>
>>>
>>> str7
'rohan@123 and Amit@456 are the 2 IDS'
>>>
>>>
>>>
>>>
>>> str7 = 'rohan@12 and Amit@456 are the 2 IDS'
>>>
>>>
>>>
>>> x = re.findall('[a-z]+@\d{3}',str7,re.I)
>>> x
['Amit@456']
>>>
>>>
>>>
>>> x = re.findall('[a-z]+@\d{1,3}',str7,re.I)
>>> x
[]
>>>
>>>\d{3} -> \d\d\d
	\d{2,6} -> min -> \d\d  max -> \d\d\d\d\d\d
	\d{2,} -> min -> \d\d max -> unlimited
  \d{,5} -> min -> 1 , max --> \d\d\d\d\d
>>> x = re.findall('[a-z]+@\d{1,3}',str7,re.I)
>>> x
['rohan@12', 'Amit@456']
>>>
>>>
>>> str7 = 'rohan@12 and Amit@456789 are the 2 IDS'
>>>
>>> x = re.findall('[a-z]+@\d{1,3}',str7,re.I)
>>> x
['rohan@12', 'Amit@456']
>>>
>>>
>>> x = re.findall('[a-z]+@\d{1,3} ',str7,re.I)
>>> x
['rohan@12 ']
>>>
>>> x = re.findall('[a-z]+@\d{2,} ',str7,re.I)
>>>
>>> x
['rohan@12 ', 'Amit@456789 ']
>>>
>>>
>>>
>>> str2
'RRRRRRohan Python'
>>>
>>>
>>>
>>> str10 = 'RRRohhhan Pythonn'
>>>
>>>
>>> x = re.match('RRRoh+an',str10)
>>>
>>> x.group()
'RRRohhhan'
>>>
>>>
>>> # + says preceeding char should come 1 or more times
...
>>>
>>>
>>> x = re.match('RRRohhha+n',str10)
>>>
>>> x.group()
'RRRohhhan'
>>>
>>>
>>> str10
'RRRohhhan Pythonn'
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>> x = re.match('rohi*an',str1)
>>>
>>> x
>>>
>>>
>>> x = re.match('roha+n',str1)
>>> x
<_sre.SRE_Match object at 0x00000000032AC780>
>>>
>>> x.group()
'rohan'
>>>
>>> x = re.match('roha*n',str1)
>>> x.group()
'rohan'
>>>
>>> # * says preceeding char can come zero or more times
...
>>>
>>>
>>>
>>> str2
'RRRRRRohan Python'
>>>
>>>
>>> x = re.match('R*',str2)
>>> x.group()
'RRRRR'
>>>
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>> x = re.match('roha*n',str1)
>>> x.group()
'rohan'
>>>
>>>
>>>
>>>
>>> str11 = '''Hello world
... how r you'''
>>>
>>>
>>> str11
'Hello world\nhow r you'
>>>
>>>
>>> x = re.match('.+',str11)
>>> x.group()
'Hello world'
>>>
>>>
>>> x = re.match('.+',str11,re.DOTALL)
>>> x.group()
'Hello world\nhow r you'
>>>
>>>
>>>
>>>
>>> x = re.match('.*',str11,re.DOTALL)
>>> x.group()
'Hello world\nhow r you'
>>>
>>>
>>>
>>>
>>> str1
'rohan Python Rstforum'
>>>
>>>
>>>
>>> x = re.search('P....n',str1)
>>> x.group()
'Python'
>>>
>>>
>>> x = re.sub('P....n','Automation',str1)
>>>
>>> x
'rohan Automation Rstforum'
>>>
>>>
>>> log = 'My PC has ip 192.16.7.1 and yours has 1.1.1.1'
>>>
>>>
>>>
>>>
>>> x = re.findall('\d\d\d.\d\d\d.\d\d\d.\')
  File "<stdin>", line 1
    x = re.findall('\d\d\d.\d\d\d.\d\d\d.\')
                                           ^
SyntaxError: EOL while scanning string literal
>>>
>>>
>>>
>>> x = re.findall('\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}',log)
>>>
>>> x
['192.16.7.1', '1.1.1.1']
>>>
>>>
>>> log = 'My PC has ip 123456543234561 and yours has 1.1.1.1'
>>>
>>> x = re.findall('\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}',log)
>>>\
>>> x
['123456543234561', '1.1.1.1']
>>>
>>> x = re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',log)
>>>
>>> x
['1.1.1.1']
>>>
>>>
>>> str1 = "rohan+Python"
>>>
>>> x = re.match('rohan+Python',str1)
>>>
>>> x
>>>
>>>
>>> x = re.match('rohan\+Python',str1)
>>> x
<_sre.SRE_Match object at 0x00000000032AC7E8>
>>>
>>> x.group()
'rohan+Python'

Multi threading

Race condition

#race condition
import threading
x = 0
def increment_global():
    global x
    x += 1
def taskOfThread():
    for i in range(500000):
        increment_global()
def main():
    t1 = threading.Thread(target=taskOfThread)
    t2 = threading.Thread(target=taskOfThread)
    t1.start()
    t1.join()
    t2.start()
    t2.join()
if __name__ == '__main__':
    for f in range(5):
        main()
        print(f"x = {x} after iteration {f}")

Context Switching

import time
from threading import Thread
def paanipoori():
    print("paani")
    time.sleep(3)
    print("poori")

    
t1 = Thread(target = paanipoori)
t2 = Thread(target = paanipoori)
t3 = Thread(target = paanipoori)
t1.start()
t2.start()
t3.start()

Semaphore

import threading
import time
sem = threading.Semaphore()
def fun1():
    print("function1 starting")
    sem.acquire()
    for x in range(1,5):
        print(f"function1 working {x}")
        time.sleep(1)
    sem.release()
    print("function1 finished")
def fun2():
    print("function2 starting")
    while not sem.acquire(blocking=False):
        print("Fun2 no semaphore available")
        time.sleep(1)
    else:
        print("got semaphore")
        for x in range(1,5):
            print(f"function2 working {x}")
            time.sleep(1)
    print("fun2 finished")
    sem.release()
t1 = threading.Thread(target=fun1)
t2 = threading.Thread(target=fun2)
t1.start()
t2.start()
print("All threads done! exiting!")

Locks

#locks
from threading import Lock, Thread
l = Lock()
g = 0
def add_one():
    global g
    l.acquire()
    g +=1
    l.release()
def add_two():
    global g
    l.acquire()
    g+=2
    l.release()

threads = []

for func in [add_one,add_two]:
    threads.append(Thread(target=func))
    threads[-1].start()

for eachthread in threads:
    eachthread.join()

print(g)

Multi-Processing

import multiprocessing
import os

def worker1():
    print(f"Process ID for worker1: {os.getpid()}")

def worker2():
    print(f"Process ID for worker 2: {os.getpid()}")
if __name__ == "__main__":

    p1 = multiprocessing.Process(target = worker1)
    p2 = multiprocessing.Process(target = worker2)

    print(f"Process ID of Main Process: {os.getpid()}")

    p1.start()
    p2.start()

    print(f"Process ID of p1 using mp: {p1.pid}")
    print(f"Process ID of p2 using mp: {p2.pid}")

    p1.join()
    p2.join()

    print(f"Process p1 is alive: {p1.is_alive()}")
    print(f"Process p2 is alive: {p2.is_alive()}")

Queue

import multiprocessing

L = multiprocessing.Queue(maxsize=6)
print(L.qsize())

L.put(9)
L.put(8)
L.put(3)
L.put(5)
L.put(2)
L.put(6)

print("Full:", L.full())
print("Size:", L.qsize())

L.get()
L.get()
L.get()
L.get()
L.get()
L.get()

print("Empty:", L.empty())

Excel with Python


from openpyxl import load_workbook, Workbook

mywb = load_workbook(
    "C:\\Users\\Rohan\\Documents\\DataHandling\\XL1.xlsx"
)
mywb = Workbook()
print(mywb.sheetnames)
mywb.create_sheet("Manage", 3)
mysh = mywb["Manage"]
mycell = mysh["C4"]
print(mycell.value)
mycell.value = "Python"
myblock = mysh["F1:H10"]
for eachrow in myblock:
    for eachcell in eachrow:
        eachcell.value = "Future"
mywb.save("students1.xlsx")

import openpyxl

path = "C:\\Users\\Rohan\\Documents\\DataHandling\\XL2.xlsx"
wb_obj = openpyxl.load_workbook(path)
sh_obj = wb_obj.active
cell_obj = sh_obj.cell(row=1, column=1)
print("Value of the first cell is", cell_obj.value)
print("Total rows are:", sh_obj.max_row)
print("Total columns are:", sh_obj.max_column)
for i in range(1, sh_obj.max_column + 1):
    cell_obj = sh_obj.cell(row=1, column=i)
    print("Names of the columns are", cell_obj.value)
for j in range(1, sh_obj.max_row + 1):
    cell_obj = sh_obj.cell(row=j, column=2)
    print("the names are", cell_obj.value)
for i in range(1, sh_obj.max_column + 1):
    cell_obj = sh_obj.cell(row=3, column=i)
    print(cell_obj.value)
-----------------------------------------------
import openpyxl

wb = openpyxl.Workbook()
sheet = wb.active
sheet_title = sheet.title
print("sheet name:" + sheet_title)
sheet.title = "Accounts"
print("sheet is renamed as:" + sheet.title)
c1 = sheet.cell(row=1, column=1)
c1.value = "RST"
c2 = sheet.cell(row=1, column=2)
c2.value = "Forum"
c3 = sheet["A3"]
c3.value = "Jay"
c4 = sheet["B2"]
c4.value = "Mital"
wb.save("C:\\Users\\Rohan\\Documents\\DataHandling\\XL3.xlsx")
-------------------------------------
import openpyxl
wb = openpyxl.Workbook()
sheet = wb.active
sheet.cell(row=1, column=1).value='Sunny'
sheet.cell(row=1, column=2).value='Leone'
sheet.row_dimensions[1].height=70
sheet.column_dimensions['B'].width=20
wb.save('C:\\Users\\Rohan\\Documents\\DataHandling\\dimension.xlsx')
---------------------------------------
import openpyxl

wb = openpyxl.Workbook()
sheet = wb.active
sheet.merge_cells("A1:D4")
sheet.cell(row=1, column=1).value = "cells merged together"
sheet.merge_cells("C6:D6")
sheet.cell(row=3, column=6).value = "2cells"
wb.save(
    "C:\\Users\\Rohan\\Documents\\RSTForum\\Python Morning\\DataHandling\\merge.xlsx"
)
-------------------------------------------------

Word Handling with Python

import docx
doc = docx.Document()
doc.add_heading("RST Forum", 0)
network_para = doc.add_paragraph("Networking\n")
py_para = doc.add_paragraph("Python\n")
cloud_para = doc.add_paragraph("Cloud\n")
sec_para = doc.add_paragraph("Security\n")
col_para = doc.add_paragraph("Collaboration\n")
serv_para = doc.add_paragraph("Servers\n")

network_para.add_run("Foundation of next generation technology").bold=True
py_para.add_run("Foundation for automation").italic=True
cloud_para.add_run("Reduce capex & opex").underline=True
sec_para.add_run("Naam hai bulla, rakhta hun khullam khulla")
col_para.add_run("Converged architecture")
serv_para.add_run("Goli nai maarenge, keh ke lenge uski")

doc.add_page_break()
doc.add_heading("Coming up: Nex Gen Tech", 2)
doc.add_picture("C:\\Users\\Rohan\\Desktop\\test.png")

doc.save("C:\\Users\\Rohan\\Desktop\\doc1.docx")
---------------------------------------------------------
from docx import Document
#Document class ka instance banaya -> existing file -> doc
doc = Document("C:\\Users\\Rohan\\Desktop\\doc1.docx")
print("List of paragraph objects")
#doc.paragraphs -> list of paragraphs store at different memory locations in RAM
print(doc.paragraphs)
print("List of run objects in the paragraph")
#0th element of paragraph list is the heading, runs are the sentences
#doc.paragraphs[0].runs shows you the memory location of the sentences inside the heading
print(doc.paragraphs[0].runs)
#doc.paragraphs[0].text shows you the heading of the paragraph
print(doc.paragraphs[0].text)
for para in doc.paragraphs:
#doc.paragraphs.text shows you the whole data of the paragraph
    print(para.text)