Python Flashcards

1
Q

What is Python?

A
  • Python is a high-level, interpreted, interactive, and object-oriented scripting language.
  • Python is designed to be highly readable and compatible with different platforms such as Mac, Windows, Linux
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Python is an interpreted language. Explain.

A

An interpreted language is any programming language where the source code is run through an interpreter which then reads statements line by line, “interpreting” the code into something the machine can understand on the fly.

This is opposed to compiled languages which must have their code parsed through a compiler that converts the source code into machine code before it can actually be run on a machine.

Programs written in Python run directly from the source code, with no intermediary compilation step.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is the difference between lists and tuples?

A

Lists

Lists are mutable, i.e., they can be edited
Lists are usually slower than tuples
Lists consume a lot of memory
Lists are less reliable in terms of errors as unexpected changes are more likely to occur
Lists consist of many built-in functions.
Syntax:
list_1 = [10, ‘Intellipaat’, 20]

Tuples

Tuples are immutable (they are lists that cannot be edited)
Tuples are faster than lists
Tuples consume less memory when compared to lists
Tuples are more reliable as it is hard for any unexpected change to occur
Tuples do not consist of any built-in functions.
Syntax:
tup_1 = (10, ‘Intellipaat’ , 20)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What are the Key features of Python?

A
  • Python is an interpreted language, so it doesn’t need to be compiled before execution
  • Python is dynamically typed, so there is no need to declare a variable with the data type. Python Interpreter will identify the data type on the basis of the value of the variable.
  • Python follows an object-oriented programming paradigm.
    Python has classes, inheritance, and all other usual OOPs concepts.
    Except Python does not have access specifiers (public and private keywords).
  • Python is a cross-platform language and general purpose
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Explain the difference between list, tuple, and set.

A

List: Ordered, mutable, allows duplicates. Example: [1, 2, 3]
Tuple: Ordered, immutable, allows duplicates. Example: (1, 2, 3)
Set: Unordered, mutable, does not allow duplicates. Example: {1, 2, 3}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you reverse a string in Python?

A

Using slicing: reversed_string = string[::-1].

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What are f-strings and how do you use them?

A

F-strings (formatted string literals) are a way to embed expressions inside string literals using curly braces {}. Example: name = “Alice”; greeting = f”Hello, {name}!”.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How do you generate random numbers in Python?

A

Using the random module. Example: import random; random_number = random.randint(1, 10).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What is the difference between == and is?

A

== checks for value equality, while is checks for identity (whether two references point to the same object).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What are *args and **kwargs?

A

*args allows a function to accept any number of positional arguments, while **kwargs allows a function to accept any number of keyword arguments.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What is a lambda function and where would you use it?

A

A lambda function is an anonymous, inline function defined using the lambda keyword. It is used for short, throwaway functions. Example: lambda x: x + 1.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

List functions and time complexities?

A

my_list.append(item)
Adds item x to the end of the list.
O(1) (amortized)

my_list.extend(iterable)
Extends the list by appending elements from the iterable.
O(k), where k is the length of the iterable

insert(index, x)
Description: Inserts item x at a given position index.
Time Complexity: O(n), where n is the number of elements in the list after index

remove(x
Description: Removes the first occurrence of item x. Raises ValueError if not found.
Time Complexity: O(n), where n is the number of elements in the list

pop([index])
Description: Removes and returns the item at the given position index. If no index is specified, it removes and returns the last item.
Time Complexity: O(n) if index is provided (O(1) if no index is provided)

index(x[, start[, end]])
Description: Returns the index of the first occurrence of item x in the list. Raises ValueError if not found.
Time Complexity: O(n), where n is the number of elements in the list

count(x)
Description: Returns the number of occurrences of item x in the list.
Time Complexity: O(n), where n is the number of elements in the list

sort(key=None, reverse=False)
Description: Sorts the items of the list in place (i.e., the list itself is changed).
Time Complexity: O(n log n), where n is the number of elements in the list

reverse()
Description: Reverses the elements of the list in place.
Time Complexity: O(n), where n is the number of elements in the list

copy()
Description: Returns a shallow copy of the list.
Time Complexity: O(n), where n is the number of elements in the list

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What are list comprehensions and give an example?

A

List comprehensions provide a concise way to create lists.
Example: [x for x in range(10) if x % 2 == 0] creates a list of even numbers from 0 to 9.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How do you iterate over keys and values in a dictionary?

A

Using the items() method.

for key, value in my_dict.items():
# code

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How do you merge two dictionaries?

A

Using the update method or {**dict1, dict2} in Python 3.5+.
Example: dict1.update(dict2) or merged_dict = {
dict1, **dict2}.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How do you add and remove items from a set?

A

Using add and remove methods. Example: my_set.add(item); my_set.remove(item).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What are some common use cases for sets?

A

Removing duplicates from a list, membership testing, and mathematical operations like union and intersection.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What is the difference between a module and a package?

A

A module is a single Python file, while a package is a collection of modules in directories that include a special __init__.py file.

19
Q

How do you handle dependencies in a Python project?

A

Using a requirements file (requirements.txt) and a package manager like pip.
Example: pip install -r requirements.txt.

20
Q

What is a class in Python and how do you define it?

A

A class is a blueprint for creating objects. It is defined using the class keyword.
Example:
class MyClass:
def __init__(self, value):
self.value = value

21
Q

Explain inheritance and how it works in Python.

A

Inheritance allows a class to inherit attributes and methods from another class.
Example:
class Animal:
def __init__(self, name):
self.name = name

def speak(self):
    raise NotImplementedError("Subclass must implement abstract method")

def info(self):
    return f"I am an animal named {self.name}"

class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Call the constructor of the base class
self.breed = breed

def speak(self):
    return "Woof!"

def info(self):
    return f"I am a {self.breed} named {self.name}"

class Cat(Animal):
def __init__(self, name, color):
super().__init__(name) # Call the constructor of the base class
self.color = color

def speak(self):
    return "Meow!"

def info(self):
    return f"I am a {self.color} cat named {self.name}"

Create instances of the derived classes
dog = Dog(“Buddy”, “Golden Retriever”)
cat = Cat(“Whiskers”, “black”)

Call methods on the instances
print(dog.info()) # Output: I am a Golden Retriever named Buddy
print(dog.speak()) # Output: Woof!

print(cat.info()) # Output: I am a black cat named Whiskers
print(cat.speak()) # Output: Meow!

22
Q

What are __init__ and __str__ methods?

A

__init__ is the initializer method (similar to a constructor).
__str__ returns a string representation of an object.

23
Q

What are class methods, static methods, and instance methods?

A

Key Points:

Instance Method:
Takes self as the first parameter.
Can modify object instance state.
Can access class variables using self.__class__.

Class Method:
Takes cls as the first parameter.
Can modify class state that applies across all instances.
Accessed using cls parameter.
Defined with @classmethod decorator.
@classmethod
def class_method(cls, increment):
cls.class_variable += increment
print(f”Class method called. Class variable: {cls.class_variable}”)

Static Method:
Does not take self or cls as the first parameter.
Cannot modify object instance state or class state.
Used for utility functions related to the class.
Defined with @staticmethod decorator.
@staticmethod
def static_method(x, y):
print(f”Static method called. Sum: {x + y}”)

When to Use Each:
Instance Methods: Use when you need to access or modify the instance’s attributes or call other instance methods.
Class Methods: Use when you need to access or modify the class state or when a method logically pertains to the class itself rather than any specific instance.
Static Methods: Use when the method does not need access to the instance or class; it just logically belongs to the class’s namespace.

24
Q

How do you handle exceptions in Python?

A

Using try, except, else, and finally blocks.
Example:
try:
# code
#Code that might raise an exception.
except Exception as e:
# handle exception: Code that runs if an exception occurs.
else:
# code if no exception: Code that runs if no exception occurs.
finally:
# cleanup code: Code that runs no matter what (used for cleanup).

25
Q

How do you raise an exception?

A

Using the raise keyword. Example: raise ValueError(“An error occurred”).

26
Q

How do you read and write files in Python?

A

with open(‘file.txt’, ‘r’) as file:
content = file.read()

with open(‘file.txt’, ‘w’) as file:
file.write(“Hello, world!”)

27
Q

What is the with statement and why is it used?

A

The with statement is used for resource management, ensuring that resources are properly cleaned up after use. It is commonly used with file operations.

28
Q

How do you read a CSV file in Python?

A

Using the csv module. Example:
import csv
with open(‘file.csv’, ‘r’) as file:
reader = csv.reader(file)
for row in reader:
print(row)

29
Q

What is a decorator and how do you use it?

A

A decorator is a function that modifies the behavior of another function.
Example:
def my_decorator(func):
def wrapper():
print(“Something is happening before the function is called.”)
func()
print(“Something is happening after the function is called.”)
return wrapper

@my_decorator
def say_hello():
print(“Hello!”)

30
Q

What is a closure in Python?

A

A closure is a function that retains access to the variables from its enclosing scope, even after the outer function has finished executing.

def outer_function(x):
def inner_function(y):
return x + y
return inner_function

closure = outer_function(10)
print(closure(5)) # Output: 15

31
Q

What is a generator and how does it differ from a list comprehension?

A

A Python generator is a special type of iterable, like a list or a tuple, but unlike these, it generates items one at a time and only when asked for, rather than holding them all in memory at once. This makes generators highly memory-efficient, especially when working with large datasets or streams of data.

Generators are defined using the yield statement instead of return. When a generator function is called, it returns a generator object without even beginning execution of the function. When the generator’s __next__() method is called, the function starts executing until it hits the yield statement, which returns the yielded value. The function retains its state and resumes where it left off when __next__() is called again.

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

counter = count_up_to(5)
print(next(counter)) # Output: 1
print(next(counter)) # Output: 2

Generators produce items lazily, while list comprehensions produce the entire list in memory.

32
Q

What is a context manager and how do you create one?

A

A context manager is used to manage resources with the with statement.
Example using a class:
class MyContextManager:
def __enter__(self):
# Setup code
return self

def \_\_exit\_\_(self, exc_type, exc_value, traceback):
    # Cleanup code

with MyContextManager() as manager:
# Code using the context manager

33
Q

Explain the difference between threading and multiprocessing in Python.

A

Threading:

Concurrency Model: Threading allows multiple threads to exist within a single process, sharing the same memory space. Each thread runs in the same memory space but can execute independently.

GIL (Global Interpreter Lock): Python’s Global Interpreter Lock (GIL) ensures that only one thread executes Python bytecode at a time, which can be a bottleneck for CPU-bound tasks. Despite this, threading can still be useful for I/O-bound tasks (e.g., file I/O, network operations) where waiting for external resources is more significant than CPU processing time.

Use Cases: Suitable for I/O-bound tasks, such as web scraping, network requests, or any scenario where the program spends a lot of time waiting for external resources.

Multiprocessing:

Concurrency Model: Multiprocessing involves multiple processes, each with its own memory space. Each process runs independently and can execute concurrently on multiple CPU cores, bypassing the GIL limitation.

Memory Usage: Each process has its own memory space, so communication between processes needs to be done via inter-process communication (IPC) mechanisms like pipes or message queues, which can introduce overhead.

Use Cases: Suitable for CPU-bound tasks, such as computationally intensive operations like data processing, scientific computations, or tasks that need to leverage multiple CPU cores.

34
Q

What are the different scopes in Python and their rules?

A

Local: Current function’s local scope.
Enclosing: Any enclosing function’s scope.
Global: Module-level scope.
Built-in: Python’s built-in scope.

Local Scope: Variables defined within a function or a block are in the local scope. They are accessible only within that function or block.

def func():
local_var = 10 # local scope
print(local_var)

func()
# print(local_var) # This would raise an error

Enclosing Scope: Variables in the enclosing function’s scope. This is relevant for nested functions.

def outer_func():
enclosing_var = 20 # enclosing scope
def inner_func():
print(enclosing_var)
inner_func()

outer_func()

Global Scope: Variables defined at the top level of a module or script. They are accessible throughout the module.

global_var = 30 # global scope

def func():
print(global_var)

func()
print(global_var)

Built-in Scope: Contains built-in functions and exceptions. Accessible from anywhere in the code.

print(len([1, 2, 3])) # len() is a built-in function

35
Q

What are the common built-in data types in Python?

A

Python supports the below-mentioned built-in data types:

Immutable data types:
Number
String
Tuple

Mutable data types:
List
Dictionary
Set

36
Q

How does break, continue, and pass work?

A

break: Exits the nearest enclosing loop.
continue: Skips the rest of the code in the current loop iteration and proceeds to the next iteration.
pass: A no-op placeholder used where code is required syntactically but no action is needed.

37
Q

What is a heap in Python?

A

A heap is a specialized tree-based data structure that satisfies the heap property.
In Python, heaps are implemented using the heapq module, which provides functions for heap operations.
Heaps can be either min-heaps (where the smallest element is at the root) or max-heaps (where the largest element is at the root).
By default, Python’s heapq module implements a min-heap.

38
Q

Heapq Operations and Time Complexities

A

heapq.heapify(iterable)
Description: Converts a list into a heap in-place.
Time Complexity: O(n), where n is the number of elements in the list.

heapq.heappush(heap, item)
Description: Adds item to the heap, maintaining the heap property.
Time Complexity: O(log n), where n is the number of elements in the heap.

heapq.heappop(heap)
Description: Removes and returns the smallest item from the heap, maintaining the heap property.
Time Complexity: O(log n), where n is the number of elements in the heap.

heapq.nlargest(n, iterable)
Description: Returns the n largest elements from the dataset defined by iterable.
Time Complexity: O(n log n), where n is the number of elements in the dataset.

heapq.nsmallest(n, iterable)
Description: Returns the n smallest elements from the dataset defined by iterable.
Time Complexity: O(n log n), where n is the number of elements in the dataset.

import heapq

heap = [1, 3, 5, 7, 9]
heapq.heapify(heap) # Convert list to heap

For lists or tuples the first item in the list will be used as key

39
Q

Simulate max heap behavior with heapq

A

import heapq

Existing list
data = [10, 20, 5, 15, 30]

Step 1: Negate all values
negated_data = [-x for x in data]

Step 2: Convert the negated list into a heap
heapq.heapify(negated_data)

Function to push an item onto the max-heap
def push(heap, item):
heapq.heappush(heap, -item) # Negate the item to simulate max-heap behavior

Function to pop the largest item from the max-heap
def pop(heap):
return -heapq.heappop(heap) # Negate the item to return it to its original form

Function to peek at the largest item in the max-heap
def peek(heap):
return -heap[0] # Negate the smallest item (which is the negated largest item)

40
Q

Make queue in python? Show operations and time complexity

A

import collections

Initialize an empty deque
dq = deque()

append(item)
Description: Adds item to the right end of the deque.
Time Complexity: O(1)

appendleft(item)
Description: Adds item to the left end of the deque.
Time Complexity: O(1)

pop()
Description: Removes and returns the item from the right end of the deque.
Time Complexity: O(1)

popleft()
Description: Removes and returns the item from the left end of the deque.
Time Complexity: O(1)

not important optional to learn

extend(iterable)
Description: Adds all elements from iterable to the right end of the deque.
Time Complexity: O(k), where k is the number of elements in the iterable

extendleft(iterable)
Description: Adds all elements from iterable to the left end of the deque, in reversed order.
Time Complexity: O(k), where k is the number of elements in the iterable

rotate(n)
Description: Rotates the deque n steps to the right (if n is positive) or left (if n is negative).
Time Complexity: O(n), where n is the number of elements in the deque

clear()
Description: Removes all elements from the deque.
Time Complexity: O(n), where n is the number of elements in the deque

copy()
Description: Returns a shallow copy of the deque.
Time Complexity: O(n), where n is the number of elements in the deque

41
Q

Recursive DFS from an adjacency list

A

def dfs_recursive(graph, start, visited=None):
if visited is None:
visited = set()

visited.add(start)
print(start)  # Process the node

for neighbor in graph[start]:
    if neighbor not in visited:
        dfs_recursive(graph, neighbor, visited)

return visited

Example usage
graph = {
‘A’: [‘B’, ‘C’],
‘B’: [‘A’, ‘D’, ‘E’],
‘C’: [‘A’, ‘F’],
‘D’: [‘B’],
‘E’: [‘B’, ‘F’],
‘F’: [‘C’, ‘E’]
}

Start DFS from node ‘A’
dfs_recursive(graph, ‘A’)

41
Q

Iterative DFS from an adjacency list

A

DFS uses stack

def dfs_iterative(graph, start):
visited = set() # To keep track of visited nodes
stack = [start] # Initialize the stack with the start node

while stack:
    node = stack.pop()  # Remove and get the last node added to the stack
    
    if node in visited:
        continue
    
    print(node)  # Process the node
    visited.add(node)  # Mark the node as visited
    
    # Add all unvisited neighbors to the stack
    for neighbor in graph[node]:
        if neighbor not in visited:
            stack.append(neighbor)

Example usage
graph = {
‘A’: [‘B’, ‘C’],
‘B’: [‘A’, ‘D’, ‘E’],
‘C’: [‘A’, ‘F’],
‘D’: [‘B’],
‘E’: [‘B’, ‘F’],
‘F’: [‘C’, ‘E’]
}

Start DFS from node ‘A’
dfs_iterative(graph, ‘A’)

42
Q

BFS iterative from an adjacency list

A

from collections import deque

def bfs(graph, start):
visited = set() # To keep track of visited nodes
queue = deque([start]) # Initialize the queue with the start node

while queue:
    node = queue.popleft()  # Remove and get the first node in the queue
    
    if node in visited:
        continue
    
    print(node)  # Process the node
    visited.add(node)  # Mark the node as visited
    
    # Add all unvisited neighbors to the queue
    for neighbor in graph[node]:
        if neighbor not in visited:
            queue.append(neighbor)

Example usage
graph = {
‘A’: [‘B’, ‘C’],
‘B’: [‘A’, ‘D’, ‘E’],
‘C’: [‘A’, ‘F’],
‘D’: [‘B’],
‘E’: [‘B’, ‘F’],
‘F’: [‘C’, ‘E’]
}

Start BFS from node ‘A’
bfs(graph, ‘A’)