├── .gitignore
├── Architecture.md
├── Asynchrony_and_Concurrency_Python.md
├── NoSQL.md
├── OOP.md
├── Python_General.md
├── Queues.md
├── README.md
├── SQL.md
└── Testing.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vscode
2 | ./.idea
3 | **/.DS_Store
4 | ./.gitignore
5 |
6 | **/__pycache__
7 | **/.pytest_cache
8 | **/.idea
9 |
10 | .env
11 | .env.prod
12 | .env.dev
13 |
14 | /venv
--------------------------------------------------------------------------------
/Architecture.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | During interviews with senior developers, a separate interview is allocated to test the skill of an architect. In the case of a middle developer, this block may not exist.
4 |
5 | If it does get included in the interview program, it might be limited to a couple of questions about your experience and case studies, such as why you chose that particular architecture in a particular case. It may seem that the interviewer thinks your solution is not the best, but it is not. The interviewer needs to understand how you made the decision. If the choice of architecture and solution was not made by you, feel free to say so.
6 |
7 | It is equally important to understand the basic postulates of the architecture: extensibility, scalability, fault tolerance. Look at sample questions:
8 |
9 | - You have your own online cinema. How to implement the functionality of email-sending to users?
10 | - How can a service or database be scaled?
11 | - Tell me what is balancing? What balancing algorithms do you know?
12 | - If you were making an online movie theater, how would you implement video uploads? How would a video player work?
--------------------------------------------------------------------------------
/Asynchrony_and_Concurrency_Python.md:
--------------------------------------------------------------------------------
1 | # Asynchrony and Concurrency in Python
2 |
3 | ### 🔶 1. What is GIL? What is it for?
4 |
5 | ---
6 | #### Answer:
7 | GIL (Global Interpreter Lock) is a mechanism used in the CPython implementation of Python to prevent multiple native threads from executing Python bytecodes at once. This lock is necessary because CPython's memory management is not thread-safe. GIL ensures that only one thread executes Python bytecode at a time, avoiding conflicts between threads over the Python interpreter's memory.
8 |
9 | ### Example:
10 | ```python
11 | import threading
12 |
13 | def my_func():
14 | x = 0
15 | for i in range(1000000):
16 | x += 1
17 |
18 | # create 2 threads
19 | t1 = threading.Thread(target=my_func)
20 | t2 = threading.Thread(target=my_func)
21 |
22 | # start the threads
23 | t1.start()
24 | t2.start()
25 | ```
26 | In this example, even though we have two threads running the same function, GIL will not allow them to run simultaneously, so the overall execution time will be similar to running the function only once on a single thread.
27 | ### 🔶 2. How is a thread different from a process?
28 |
29 | ---
30 | #### Answer:
31 | A thread is a lightweight, independent unit of execution that can run within a process. Threads within a process share the same memory space, making it easy for them to share data and communicate with each other. A process, on the other hand, is a self-contained execution environment that has its own memory space and resources.
32 |
33 | ### 🔶 3. Tell us about the race condition and thread safety.
34 |
35 | ---
36 | #### Answer:
37 | A race condition occurs when multiple threads access shared data or resources simultaneously, and the outcome of the program depends on the order in which the threads execute. Thread safety is the property of an application or library that it can handle multiple threads accessing shared data or resources without introducing race conditions.
38 |
39 | #### Example:
40 | ```python
41 | import threading
42 |
43 | x = 0
44 |
45 | def increment():
46 | global x
47 | for i in range(1000000):
48 | x += 1
49 |
50 | def decrement():
51 | global x
52 | for i in range(1000000):
53 | x -= 1
54 |
55 | # create 2 threads
56 | t1 = threading.Thread(target=increment)
57 | t2 = threading.Thread(target=decrement)
58 |
59 | # start the threads
60 | t1.start()
61 | t2.start()
62 |
63 | # wait for the threads to finish
64 | t1.join()
65 | t2.join()
66 |
67 | print(x)
68 | ```
69 | In this example, we have two threads running simultaneously that increment and decrement a shared variable x. The final value of x will depend on the order in which the threads execute, which can lead to race conditions.
70 |
71 | ### 🔶 4. What mechanisms for synchronizing access to shared resources do you know?
72 |
73 | ---
74 | #### Answer:
75 | Some mechanisms for synchronizing access to shared resources include:
76 |
77 | - Locks: a mechanism that allows only one thread to execute a critical section of code at a time.
78 | - Semaphores: a mechanism that allows multiple threads to access a shared resource, but with a limit on the number of threads that can access the resource at the same time.
79 | - Monitors: a mechanism that allows only one thread to execute a critical section of code at a time, and also provides a mechanism for threads to wait for specific conditions to be met before continuing execution.
80 |
81 | #### Example:
82 | ```python
83 | import threading
84 |
85 | # Using locks
86 | x = 0
87 | lock = threading.Lock()
88 |
89 | def increment():
90 | global x
91 | with lock:
92 | for i in range(1000000):
93 | x += 1
94 |
95 | def decrement():
96 | global x
97 | with lock:
98 | for i in range(1000000):
99 | x -= 1
100 |
101 | # Using semaphores
102 | semaphore = threading.Semaphore(1)
103 |
104 | def increment():
105 | global x
106 | semaphore.acquire()
107 | for i in range(1000000):
108 | x += 1
109 | semaphore.release()
110 |
111 | def decrement():
112 | global x
113 | semaphore.acquire()
114 | for i in range(1000000):
115 | x -= 1
116 | semaphore.release()
117 | ```
118 | In this example, we use locks and semaphores to synchronize access to the shared variable x, making sure that only one thread can access the variable at a time, avoiding race conditions.
119 |
120 | ### 🔶 5. What mechanisms of interaction of processes do you know?
121 |
122 | ---
123 | #### Answer:
124 | Some mechanisms of interaction of processes include:
125 | - Inter-process communication (IPC) mechanisms such as pipes, sockets, and message queues
126 | - Signals, which are used to send simple notifications between processes
127 | - Shared memory, which allows processes to directly access the same memory space.
128 |
129 | ### 🔶 6. What is asynchronous I/O?
130 |
131 | ---
132 | #### Answer:
133 | Asynchronous I/O is a method of input/output operations in which the process does not wait for the I/O operation to complete before continuing execution. This allows for more efficient use of system resources, as the process can perform other tasks while the I/O operation is in progress.
134 |
135 | #### Example:
136 | ```python
137 | import asyncio
138 |
139 | async def read_file():
140 | # Open the file in non-blocking mode
141 | file = open("file.txt", "r", buffering=0)
142 | # Read the first line of the file
143 | line = await file.readline()
144 | print(line)
145 | file.close()
146 |
147 | async def main():
148 | await read_file()
149 |
150 | asyncio.run(main())
151 | ```
152 | In this example, the await file.readline() is an asynchronous I/O operation that reads the first line of the file, the program does not wait for the operation to finish, it can execute the next line while it is reading the file.
153 |
154 | ### 🔶 7. What are coroutines? How do they work?
155 |
156 | ---
157 | #### Answer:
158 | Coroutines are a type of lightweight, cooperative threads that allow for concurrency without the need for multiple threads. Coroutines can yield control to other coroutines, allowing them to execute, and then resume execution later. They are implemented using the "yield" keyword and are similar to generators, but with more features for concurrency.
159 |
160 | #### Example:
161 | ```python
162 | import asyncio
163 |
164 | async def my_coroutine():
165 | print("Starting coroutine")
166 | await asyncio.sleep(1)
167 | print("Ending coroutine")
168 |
169 | async def main():
170 | await my_coroutine()
171 |
172 | asyncio.run(main())
173 | ```
174 | In this example, my_coroutine() is a coroutine that uses the await asyncio.sleep(1) to simulate a delay of one second. The await keyword is used to allow other coroutines to run while this coroutine is paused.
175 |
176 | ### 🔶 8. What is the use of the async/await construct in Python?
177 |
178 | ---
179 | #### Answer:
180 | The async/await construct in Python is used to write asynchronous code in a synchronous-like fashion. The "async" keyword is used to define an asynchronous function and the "await" keyword is used to call other asynchronous functions from within an asynchronous function.
181 |
182 | ### 🔶 9. How is the EventLoop arranged?
183 |
184 | ---
185 | #### Answer:
186 | An EventLoop is a mechanism that allows for the scheduling and execution of asynchronous code. It runs in a single thread and manages the execution of tasks, such as I/O operations, by scheduling them to be executed as soon as their resources become available. EventLoop is an essential part of asyncio library which provides an abstract event-driven asynchronous I/O framework.
187 |
188 | #### Example:
189 | ```python
190 | import asyncio
191 |
192 | async def my_task():
193 | print("Starting task")
194 | await asyncio.sleep(1)
195 | print("Ending task")
196 |
197 | async def main():
198 | # Create an event loop
199 | loop = asyncio.get_event_loop()
200 | # Schedule the task using the loop
201 | loop.create_task(my_task())
202 | # Run the loop
203 | loop.run_forever()
204 |
205 | asyncio.run(main())
206 | ```
207 | In this example, we create an event loop using asyncio.get_event_loop() and schedule a task using loop.create_task(my_task()). The event loop is then run using loop.run_forever() which schedules and runs the task as soon as resources become available.
208 |
209 | ### 🔶 10. What is the purpose of the async with statement in Python? Provide an example?
210 |
211 | ---
212 | #### Answer
213 | The async with statement is used for managing resources in an asynchronous context, similar to the regular with statement for synchronous code. It's commonly used for working with asynchronous I/O resources that need to be acquired and released safely.
214 |
215 | #### Example:
216 | ```python
217 | import asyncio
218 |
219 | class AsyncResource:
220 | async def __aenter__(self):
221 | print("Acquiring resource asynchronously")
222 | await asyncio.sleep(1)
223 | return self
224 |
225 | async def __aexit__(self, exc_type, exc_val, exc_tb):
226 | print("Releasing resource asynchronously")
227 |
228 | async def main():
229 | async with AsyncResource() as resource:
230 | print("Using async resource")
231 |
232 | if __name__ == "__main__":
233 | asyncio.run(main())
234 | ```
235 |
236 | ### Back to top ⬆️
237 |
--------------------------------------------------------------------------------
/NoSQL.md:
--------------------------------------------------------------------------------
1 | # NoSQL
2 |
3 | ### 🔶 1. What is NoSQL?
4 |
5 | ---
6 | #### Answer:
7 | NoSQL stands for "Not Only SQL" and refers to a type of database management system that is designed to handle large amounts of unstructured or semi-structured data. It does not rely on the traditional table-based relational model and typically does not use SQL as the query language.
8 | ### 🔶 2. What are some examples of NoSQL databases?
9 |
10 | ---
11 | #### Answer:
12 | MongoDB, Cassandra, Redis, and Couchbase are some examples of popular NoSQL databases.
13 | ### 🔶 3. What is the main difference between NoSQL and SQL databases?
14 |
15 | ---
16 | #### Answer:
17 | SQL databases are based on the relational model and rely on a fixed schema, while NoSQL databases are more flexible and do not have a fixed schema. SQL databases use SQL as the query language, while NoSQL databases may use different query languages. SQL databases are better suited for structured data, while NoSQL databases are better suited for unstructured or semi-structured data.
18 | ### 🔶 4. What is a document-based NoSQL database?
19 |
20 | ---
21 | #### Answer:
22 | A document-based NoSQL database stores data in the form of documents, such as JSON or BSON, instead of tables. Each document contains a set of fields, similar to columns in a table, and can have a nested structure. MongoDB is an example of a document-based NoSQL database.
23 | ### 🔶 5. What are the advantages of using a NoSQL database?
24 |
25 | ---
26 | #### Answer:
27 | NoSQL databases are highly scalable and can handle large amounts of data. They are also designed to be highly available and can be distributed across multiple servers. NoSQL databases also have a more flexible schema, which allows for easier data modeling and faster development.
28 | ### 🔶 6. What are the disadvantages of using a NoSQL database?
29 |
30 | ---
31 | #### Answer:
32 | NoSQL databases may lack some of the advanced features of SQL databases, such as support for complex queries and transactions. They may also have less mature ecosystem and tooling.
33 | ### 🔶 7. How would you design a NoSQL database for a social media application?
34 |
35 | ---
36 | #### Answer:
37 | For a social media application, a NoSQL database such as MongoDB would be suitable because it can handle large amounts of unstructured data, such as user profiles and posts. The data model would likely include collections for users, posts, comments, and likes. Indexes could be created on fields such as the user's name, the post's timestamp, and the comment's timestamp to improve the performance of queries
38 |
39 | ### Back to top ⬆️
40 |
--------------------------------------------------------------------------------
/OOP.md:
--------------------------------------------------------------------------------
1 | # OOP
2 |
3 | ### 🔶 1. Explain the basic principles of OOP.
4 |
5 | ---
6 | #### Answer:
7 | Object-oriented programming (OOP) is a programming paradigm that uses objects, which are instances of classes, to represent and manipulate data. The basic principles of OOP include encapsulation, inheritance, and polymorphism.
8 | ### 🔶 2. Are you familiar with SOLID? Look at the code, are there any SOLID principles violated here? How can this be fixed?
9 |
10 | ---
11 | #### Answer:
12 | SOLID is a set of five principles for object-oriented software design, which stands for Single responsibility, Open-closed, Liskov substitution, Interface segregation, and Dependency Inversion.
13 |
14 | ### Example:
15 | ```python
16 | class Dog:
17 | def __init__(self, name, breed):
18 | self.name = name
19 | self.breed = breed
20 | def bark(self):
21 | print("Woof!")
22 | def fetch(self):
23 | print("Fetching...")
24 | def playDead(self):
25 | print("Playing dead...")
26 | def rollOver(self):
27 | print("Rolling over...")
28 | def chaseTail(self):
29 | print("Chasing tail...")
30 |
31 | # This class violates the Single Responsibility Principle as it has too many methods which are doing different tasks.
32 | ```
33 | It can be fixed by splitting the class into multiple classes each with a single responsibility
34 |
35 | ```python
36 | class Dog:
37 | def __init__(self, name, breed):
38 | self.name = name
39 | self.breed = breed
40 | def bark(self):
41 | print("Woof!")
42 |
43 | class Tricks:
44 | def fetch(self):
45 | print("Fetching...")
46 | def playDead(self):
47 | print("Playing dead...")
48 | def rollOver(self):
49 | print("Rolling over...")
50 | def chaseTail(self):
51 | print("Chasing tail...")
52 |
53 | ```
54 | ### 🔶 3. What OOP patterns are you familiar with?
55 |
56 | ---
57 | #### Answer:
58 |
59 | Some common OOP patterns include:
60 | - Singleton pattern: which ensures that a class has only one instance
61 | - Factory pattern: which creates objects without specifying the exact class of object that will be created
62 | - Decorator pattern: which allows behavior to be added to an individual object, either statically or dynamically
63 | - Observer pattern: which allows objects to be notified of changes to other objects
64 | ### 🔶 4. How is an interface different from an abstract class?
65 |
66 | ---
67 | #### Answer:
68 | An interface is a collection of abstract methods (methods with no implementation) that a class must implement. An abstract class is a class that contains one or more abstract methods, but may also have implemented methods. An interface defines a contract, but an abstract class can provide a partial implementation.
69 | ### 🔶 5. What are class methods defined through the @classmethod decorator? What are they needed for?
70 |
71 | ---
72 | #### Answer:
73 | Class methods are methods that are bound to the class and not the instance of the object. They are defined using the @classmethod decorator and take the class as the first argument instead of self. They are useful for creating alternative constructors for a class.
74 |
75 | ### Example:
76 | ```python
77 | class Dog:
78 | def __init__(self, name, breed):
79 | self.name = name
80 | self.breed = breed
81 |
82 | @classmethod
83 | def create_from_tuple(cls, name_breed_tuple):
84 | return cls(*name_breed_tuple)
85 |
86 | dog = Dog.create_from_tuple(("Fido", "Golden Retriever"))
87 | print(dog.name)
88 | ```
89 | ### 🔶 6. How are private attributes declared in Python?
90 |
91 | ---
92 | #### Answer:
93 | In Python, private attributes are denoted by a double leading underscore. This is a convention indicating that the attribute should not be accessed directly from outside the class, although it can still be accessed if necessary.
94 |
95 | ### Example:
96 | ```python
97 | class Dog:
98 | def __init__(self, name, breed):
99 | self.__name = name
100 | self.__breed = breed
101 | def get_name(self):
102 | return self.__name
103 | def get_breed(self):
104 | return self.__breed
105 |
106 | dog = Dog("Fido", "Golden Retriever")
107 | print(dog.__name) # This will raise an AttributeError
108 | print(dog.get_name()) # This will return "Fido"
109 | ```
110 | ### 🔶 7. What is MRO in Python?
111 |
112 | ---
113 | #### Answer:
114 | The Method Resolution Order (MRO) is the order in which the interpreter looks for methods in a class hierarchy. In Python, the MRO is determined by C3, which is a linearization algorithm that finds the order of methods that avoids diamond problem and provide a consistent method resolution order. It works by first determining the depth of the class, and then the order of classes by checking the left-most class first, and then moving to the right.
115 |
116 | ### Example:
117 | ```python
118 | class A:
119 | def method(self):
120 | print("Class A method")
121 |
122 | class B(A):
123 | pass
124 |
125 | class C(A):
126 | def method(self):
127 | print("Class C method")
128 |
129 | class D(B, C):
130 | pass
131 |
132 | d = D()
133 | d.method() # Output: "Class C method"
134 | ```
135 | in the above example, python interpreter first look for the method in class D, it's not present then it looks in class B which also not present then it looks in class C and it found the method there so it will use this method.
136 |
137 | You can use the built-in help function to check the MRO of a class, it prints the order of classes that Python will look through when searching for a method.
138 | ```python
139 | help(D)
140 | ```
141 | This will output something like
142 | ```python
143 | class D(B, C)
144 | | Method resolution order:
145 | | D
146 | | B
147 | | C
148 | | A
149 | ```
150 | It lists the classes in the order that Python will look for methods in them.
151 |
152 | ### Back to top ⬆️
153 |
154 |
--------------------------------------------------------------------------------
/Python_General.md:
--------------------------------------------------------------------------------
1 | # Python general questions
2 |
3 | ### 🔶 1. What is the complexity in O-notation of the len operation of list?
4 |
5 | ---
6 | #### Answer:
7 | The complexity of the len operation of a list in Python is O(1). This is because the length of a list is stored as a separate attribute, making it a constant-time operation to retrieve the length.
8 |
9 | ### 🔶 2. And in the O-notation, the difficulty of obtaining an element by index in a list?
10 |
11 | ---
12 | #### Answer:
13 | The complexity of obtaining an element by index in a list in Python is O(1). This is because lists in Python are implemented as arrays, which allow for constant-time access to elements by index.
14 |
15 | ### 🔶 3. What is the structure of the implementation of dictionaries? How is the fight against key collisions implemented?
16 |
17 | ---
18 | #### Answer:
19 | Dictionaries in Python are implemented as a hash table. The fight against key collisions is implemented by using a technique called open addressing, which involves finding the next open slot in the table for a key-value pair that would have otherwise collided with an existing key.
20 |
21 | ### 🔶 4. How does the Garbage Collector work in Python?
22 |
23 | ---
24 | #### Answer:
25 | The Garbage Collector in Python works by periodically checking for objects in memory that are no longer being used by the program. Once such objects are identified, they are deallocated and their memory is freed up.
26 |
27 | ### 🔶 5. With what data structure is set implemented?
28 |
29 | ---
30 | #### Answer:
31 | A set in Python is implemented as a hash table. This allows for fast insertion, deletion and membership tests.
32 |
33 | ### 🔶 6. What are decorators and how do they work?
34 |
35 | ---
36 | #### Answer:
37 | Decorators in Python are a way to modify or extend the functionality of a function or class. They are implemented as functions that take another function as an argument and return a new function that usually includes the functionality of the original function.
38 | ```python
39 | def my_decorator(func):
40 | def wrapper():
41 | print("Something is happening before the function is called.")
42 | func()
43 | print("Something is happening after the function is called.")
44 | return wrapper
45 |
46 | @my_decorator
47 | def say_hello():
48 | print("hello!")
49 |
50 | say_hello()
51 | # Output:
52 | # Something is happening before the function is called.
53 | # hello!
54 | # Something is happening after the function is called.
55 |
56 | ```
57 | ### 🔶 7. What are generators and how do they work?
58 |
59 | ---
60 | #### Answer:
61 | Generators in Python are a special type of iterator that allow a programmer to iterate over a sequence of items, without the need to keep the entire sequence in memory. They are implemented as functions that use the "yield" keyword to return an iterator, instead of a list. When a generator function is called, it returns a generator object, which can be used in a for loop or with the next() function to iterate through the generated sequence.
62 | ```python
63 | def my_gen():
64 | yield 1
65 | yield 2
66 | yield 3
67 |
68 | for i in my_gen():
69 | print(i)
70 | # Output:
71 | # 1
72 | # 2
73 | # 3
74 | ```
75 | ### 🔶 8. What are context managers and how do they work?
76 |
77 | ---
78 | #### Answer:
79 | Context managers in Python are used to set up and tear down a context around a block of code. They are implemented using the "with" statement and a context manager object, which has methods such as "enter" and "exit" that are called when the context is entered and exited. This is useful for managing resources such as file and network connections, where it's important to ensure that the resources are properly closed and cleaned up after use. The "with" statement automatically handles the calls to the "enter" and "exit" methods, making it easy to ensure that the resources are properly managed, even in the presence of exceptions.
80 |
81 | ### Back to top ⬆️
82 |
--------------------------------------------------------------------------------
/Queues.md:
--------------------------------------------------------------------------------
1 | # Queues
2 |
3 | Modern architecture is hard to imagine without the use of queues. When preparing for an interview, do not lose sight of this block. The questions will focus on understanding the general ideas, the applicability of queues to tasks, and your experience with them.
4 |
5 | ### 🔶 1. What is a queue?
6 |
7 | ---
8 | #### Answer:
9 | A queue is a data structure that follows the First-In-First-Out (FIFO) principle, where the first element added to the queue is the first one to be removed.
10 | ### 🔶 2. What are some use cases for queues?
11 |
12 | ---
13 | #### Answer:
14 | Queues are often used for task management, such as scheduling background jobs, handling messages and events, and managing traffic in networks. They can also be used for buffering, load balancing, and rate limiting.
15 | ### 🔶 3. What are the main operations of a queue?
16 |
17 | ---
18 | #### Answer:
19 | The main operations of a queue are enqueue (adding an element to the queue), dequeue (removing an element from the queue), and peek (accessing the front element of the queue without removing it).
20 | ### 🔶 4. What is the difference between a queue and a stack?
21 |
22 | ---
23 | #### Answer:
24 | A queue follows the First-In-First-Out (FIFO) principle, where the first element added to the queue is the first one to be removed. A stack follows the Last-In-First-Out (LIFO) principle, where the last element added to the stack is the first one to be removed.
25 | ### 🔶 5. How would you implement a queue in Python?
26 |
27 | ---
28 | #### Answer:
29 | A queue can be implemented in Python using a list with the append() method for enqueue and the pop(0) method for dequeue.
30 |
31 | #### Example:
32 | ```python
33 | queue = []
34 | queue.append(1) # enqueue 1
35 | queue.append(2) # enqueue 2
36 |
37 | print(queue.pop(0)) # dequeue 1
38 | print(queue) # [2]
39 | ```
40 |
41 | ### 🔶 6. How would you implement a priority queue in Python?
42 |
43 | ---
44 | #### Answer:
45 | A priority queue can be implemented in Python using the heapq library. Elements are added to the queue with a priority value, and the element with the highest priority is always at the front of the queue.
46 |
47 | #### Example:
48 | ```python
49 | import heapq
50 |
51 | priority_queue = []
52 |
53 | heapq.heappush(priority_queue, (2, 'task2'))
54 | heapq.heappush(priority_queue, (3, 'task3'))
55 | heapq.heappush(priority_queue, (1, 'task1'))
56 |
57 | print(heapq.heappop(priority_queue)) # (1, 'task1')
58 | ```
59 |
60 | ### 🔶 7. What are some common use cases for message queues?
61 |
62 | ---
63 | #### Answer:
64 | Common use cases for message queues include:
65 |
66 | - Decoupling systems by allowing them to communicate asynchronously
67 | - Buffering and load leveling
68 | - Enabling the communication between microservices in a distributed system
69 | - Allowing for the reliable communication between systems with different performance characteristics
70 | - Facilitating the communication between event-driven systems
71 | - Enabling communication between processes, applications, and devices.
72 | ### 🔶 8. What are the benefits of using a message queue?
73 |
74 | ---
75 | #### Answer:
76 | Some benefits of using a message queue include: Decoupling systems, load balancing, buffering, and rate limiting. It also allows for asynchronous processing and can help prevent message loss in case of system failure.
77 |
78 | ### Back to top ⬆️
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stack Questions
2 | Technical questions may be different, but they will all be aimed at revealing your knowledge and your level. If you don't know the correct answer to a question, feel free to say so. This will save time for both you and the interviewers.
3 |
4 | Interviewers often choose a strategy where the complexity and depth of questions grows until you hit the ceiling of your current knowledge. This allows interviewers to understand your current level and whether it is enough to solve the company's problems.
5 |
6 | Remember, the more detailed the answer, the more profound knowledge the interviewer will note for himself.
7 |
8 | ---
9 | ## Consider the main topics for questions you may encounter:
10 | - ### [Python.](/Python_General.md)
11 | Here are some general questions about Python and data types
12 | - ### [Asynchrony and concurrency in Python.](Asynchrony_and_Concurrency_Python.md)
13 | For answers, you need to remember everything you know about asynchrony from the GIL to coroutines and generators
14 | - ### [OOP.](OOP.md)
15 | OOP is often asked general questions, but you may come across questions related specifically to Python. Also, we can talk about different patterns
16 | - ### [SQL.](SQL.md)
17 | Questions aimed at knowledge of SQL databases and SQL dialect. The questions can be adapted for example to PostgreSQL or MySQL
18 | - ### [NoSQL.](NoSQL.md)
19 | This block of questions may arise if you have worked with NoSQL databases
20 | - ### [Architecture.](Architecture.md)
21 | During interviews for senior developers, a separate interview is allocated to check the skills of an architect
22 | - ### [Queues](Queues.md)
23 | When preparing for an interview, do not lose sight of this block.
24 | - ### [Testing.](Testing.md)
25 | It can be about your testing experience when you write tests, and about different hacks in the tests themselves.
26 |
27 | ---
28 | ## How to prepare to interview?
29 | Repeat everything on the topics from the “Questions about the stack” block - the more thoroughly, the better. Here is the finished checklist:
30 | - [ ] [Python](/Python_General.md)
31 | - [ ] [Asynchrony and concurrency in Python](Asynchrony_and_Concurrency_Python.md)
32 | - [ ] [OOP](OOP.md)
33 | - [ ] [SQL](SQL.md)
34 | - [ ] [NoSQL](NoSQL.md)
35 | - [ ] [Queues](Queues.md)
36 | - [ ] [Architecture](Architecture.md)
37 | - [ ] [Testing](Testing.md)
38 |
39 | ---
40 | ## Signs of the Middle+ level in these blocks:
41 | - You have experience with microservice architecture, as well as experience in splitting a monolithic application into microservices.
42 | - You worked with a company-relevant stack. This is not only about Python, but about all technologies, storages, queues and CI / CD.
43 | - You talk about the disadvantages of blindly following the requirements in response to the question about good / bad practice.
44 | - If you do not know ready-made solutions, you can come up with them based on your experience and knowledge.
45 |
46 | ### Back to top ⬆️
47 |
--------------------------------------------------------------------------------
/SQL.md:
--------------------------------------------------------------------------------
1 | # SQL
2 |
3 | ### 🔶 1. What types of relationships between tables do you know?
4 |
5 | ---
6 | #### Answer:
7 | Types of relationships between tables are:
8 | - One-to-One: where one record in table A corresponds to one record in table B
9 | - One-to-Many: where one record in table A corresponds to multiple records in table B
10 | - Many-to-Many: where multiple records in table A correspond to multiple records in table B
11 | ### 🔶 2. What types of JOIN do you know? What is the difference?
12 |
13 | ---
14 | #### Answer:
15 | - INNER JOIN: only returns records where there is a match in both tables
16 | - LEFT JOIN: returns all records from the left table and any matching records from the right table
17 | - RIGHT JOIN: returns all records from the right table and any matching records from the left table
18 | - FULL OUTER JOIN: returns all records from both tables
19 | ### 🔶 3. What is selectivity?
20 |
21 | ---
22 | #### Answer:
23 | Selectivity is the degree to which the values of a column in a table are unique. A column with high selectivity has unique values, while a column with low selectivity has many repeating values. This is important when creating indexes, because an index on a column with high selectivity will be more efficient than an index on a column with low selectivity.
24 | ### 🔶 4. Have you ever profiled requests?
25 |
26 | ---
27 | #### Answer:
28 | Profiling requests is the process of measuring the performance of a database query and identifying bottlenecks. This can be done using tools such as the EXPLAIN command in SQL or a database profiler.
29 |
30 | #### Example:
31 | ```postgresql
32 | EXPLAIN SELECT * FROM users_table WHERE name = 'Alice';
33 | ```
34 | ### 🔶 5. What is the difference between explain and explain analyze?
35 |
36 | ---
37 | #### Answer:
38 | The difference between EXPLAIN and EXPLAIN ANALYZE is that EXPLAIN shows the execution plan of the query without actually running it, while EXPLAIN ANALYZE not only shows the execution plan but also runs the query and provides statistics on its performance.
39 |
40 | ### 🔶 6. In what order is the SELECT query evaluated?
41 |
42 | ---
43 | #### Answer:
44 | SELECT query is evaluated in the following order:
45 | - FROM clause
46 | - JOIN clause
47 | - WHERE clause
48 | - GROUP BY clause
49 | - HAVING clause
50 | - SELECT clause
51 | - ORDER BY clause
52 | ### 🔶 7. What is an index?
53 |
54 | ---
55 | #### Answer:
56 | An index is a database feature that allows for faster searching and sorting of data. Indexes can be created on one or more columns of a table, and are used to quickly locate specific rows in the table.
57 | ### 🔶 8. What indexes do you know?
58 |
59 | ---
60 | #### Answer:
61 | Types of indexes:
62 | - B-Tree index
63 | - Bitmap index
64 | - Hash index
65 | - Full-text index
66 | - Spatial index
67 |
68 | ### 🔶 9. What is B-Tree?
69 |
70 | ---
71 | #### Answer:
72 | B-Tree index is a balanced tree data structure that stores data in a sorted order and allows for efficient insertion, deletion and search operations. It is commonly used in databases to improve the performance of SELECT, INSERT and UPDATE operations. In a B-Tree, the data is stored in a balanced tree, so the height of the tree is always
73 |
74 | ---
75 |
76 | ## Here is a list of features that correspond to the Middle+ level:
77 | - You quickly answer simple questions about indexes.
78 | - You are answering a question about transaction isolation levels.
79 | - You have experience in query profiling and optimization.
80 | - You can write complex queries such as window functions and CTEs.
81 | - You understand when not to write complex queries.
82 |
83 | ### Back to top ⬆️
84 |
--------------------------------------------------------------------------------
/Testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | ### 🔶 1. Do you write tests? What are the types of tests?
4 |
5 | ---
6 | #### Answer:
7 | Yes, I am familiar with writing tests. There are several types of tests, including:
8 | Unit tests: tests individual units of code, such as a specific function or method, in isolation.
9 | Integration tests: tests how different units of code work together.
10 | Functional tests: tests the functionality of a system as a whole by simulating user interactions.
11 | Performance tests: tests how a system performs under a certain load or stress.
12 | Acceptance tests: tests whether a system meets the requirements of the stakeholders.
13 |
14 | ### 🔶 2. What is mock? How to use it?
15 |
16 | ---
17 | #### Answer:
18 | A mock is a replacement for an object or a function that allows you to control its behavior during a test. This is useful when you have a dependency on an external service or a resource that is not available during the test. In Python, the unittest.mock library provides the MagicMock class for creating mocks.
19 |
20 | #### Example:
21 | ```python
22 | from unittest.mock import MagicMock
23 |
24 | def my_function(dependency):
25 | return dependency.do_something()
26 |
27 | # Create a mock object
28 | mock_dependency = MagicMock()
29 |
30 | # Test the function
31 | my_function(mock_dependency)
32 |
33 | # Assert that the mock's method was called
34 | mock_dependency.do_something.assert_called()
35 | ```
36 | ### 🔶 3. How to test a function that depends on system time?
37 |
38 | ---
39 | #### Answer:
40 | To test a function that depends on system time, you can use the unittest.mock library to replace the datetime module with a mock. You can then control the current time returned by the mock.
41 |
42 | ```python
43 | from unittest.mock import MagicMock, patch
44 |
45 | def my_function():
46 | from datetime import datetime
47 | return datetime.now().hour
48 |
49 | # Test the function
50 | with patch('datetime.datetime') as mock_datetime:
51 | mock_datetime.now.return_value = datetime(year=2020, month=1, day=1, hour=10)
52 | assert my_function() == 10
53 | ```
54 |
55 | ### 🔶 4. How to check that mock was called once and with the right set of parameters?
56 |
57 | ---
58 | #### Answer:
59 | You can use the assert_called_once() and assert_called_with() methods provided by the MagicMock class to check if a mock was called with the expected parameters.
60 |
61 | #### Example:
62 | ```python
63 | mock_dependency.do_something.assert_called_once()
64 | mock_dependency.do_something.assert_called_with('arg1', 'arg2')
65 | ```
66 |
67 | ### 🔶 5. How to test an async function?
68 |
69 | ---
70 | #### Answer:
71 | To test an async function, you can use the asyncio.run() method to run the function as a coroutine, or use the unittest.TestCase.loop context manager provided by the asynctest library.
72 | #### Example:
73 | ```python
74 | import asyncio
75 |
76 | async def my_async_function():
77 | await asyncio.sleep(1)
78 | return 'Hello World'
79 |
80 | # Using asyncio.run
81 | assert asyncio.run(my_async_function()) == 'Hello World'
82 |
83 | # Using unittest.TestCase.loop
84 | import unittest
85 | from asynctest import TestCase
86 |
87 | class MyTestCase(TestCase):
88 | async def test_my_async_function(self):
89 | result = await my_async_function()
90 | self.assertEqual(result, 'Hello World')
91 | ```
92 |
93 | ### 🔶 6. How to test code that runs in a thread or process?
94 |
95 | ---
96 | #### Answer:
97 | To test code that runs in a thread or process, you can use the unittest.TestCase.run_in_executor() method to run the function in a thread or process, and use the concurrent.futures library to create a thread or process pool.
98 |
99 | #### Example:
100 | ```python
101 | import concurrent.futures
102 | import unittest
103 |
104 | def my_function():
105 | return 'Hello World'
106 |
107 | class MyTestCase(unittest.TestCase):
108 | def test_my_function(self):
109 | with concurrent.futures.ThreadPoolExecutor() as executor:
110 | future = executor.submit(my_function)
111 | self.assertEqual(future.result(), 'Hello World')
112 |
113 | with concurrent.futures.ProcessPoolExecutor() as executor:
114 | future = executor.submit(my_function)
115 | self.assertEqual(future.result(), 'Hello World')
116 | ```
117 |
118 | ### 🔶 7. How to test a web application?
119 |
120 | ---
121 | #### Answer:
122 | To test a web application in Python, there are several popular libraries and frameworks that can be used. Some of the common options include:
123 | - unittest and requests: The built-in unittest library along with the requests library can be used to send HTTP requests to the application and test the responses.
124 | - pytest and pytest-flask: pytest is a popular testing framework that can be used to write test cases for a web application built with the Flask framework.
125 | - Django test client: The built-in django.test.Client class can be used to simulate client interactions and test the views, forms, and templates for an application built using the Django framework.
126 | - WebTest, Selenium: these are other libraries that can be used for testing web applications in python.
127 | - It's important to use the right tools and libraries depending on the framework, platform and the complexity of the application.
128 |
129 |
130 | ### Back to top ⬆️
131 |
--------------------------------------------------------------------------------