- Notifications
You must be signed in to change notification settings - Fork8
ankurchavda/Python-Interview-Questions
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
- What are lambda functions? Why are they used?
A Lambda function, or an anonymous function, is a self-contained block of functionality that can be passed around and used in your code. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition.
Lambda functions are syntactic sugar and provide a cleaner way to write easy/small functions.
Python supports the functional programming paradigm. It allows to supply a function as a parameter to a different function like map, filter, etc. In such cases, elegant one time functions can be created using lambda.
What are the built-in data types that Python provides? Which of them are mutable, which are immutable?
Numeric Types:int,float,complex,bool
Sequence Types:list,tuple,range,str
Mapping Type:dict
Set Types:set,frozensetMutable:
list,set,dict
Immutable:str,tuple,range,bool,complex,int,float
- What is the difference between list and tuple?
Tuples vs Lists - Stack Overflow
Tuples have structure, lists have order -Stack Overfloww
Why are tuples faster than lists?
Tuples are faster than lists because:Tuples can be constant folded.
Tuples can be reused instead of copied.
Tuples are compact and don't over-allocate.
Tuples directly reference their elements.
Read the first two answers on this thread -Tuples faster than lists - Stack Overflow
- What is the difference between
isand==?
==is forvalue equality. Use it when you would like to know if two objects have the same value.isis forreference equality. Use it when you would like to know if two references refer to the same object.
In general, when you are comparing something to a simple type, you are usually checking for value equality, so you should use==. For example, forx==2the intention is probably to check whether x has a value equal to 2 (==), not whether x is literally referring to the same object as 2.However, there is a catch to this as well. Please refer the example in the below link.
- What could be the key in
dict?
Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can’t use lists as keys, since lists can be modified in place using index assignments, slice assignments, or methods likeappend()andextend().
Why can't lists be dictionary keys?
If lists are hashed by their ids -Looking up different lists with the same contents would produce different results, even though comparing lists with the same contents would indicate them as equivalent.
Using a list literal in a dictionary lookup would be pointless -- it would always produce a
KeyError.If lists were hashed by their contents (as tuples are) then that would lead to problems explained below -
#Suppose that the hash() function returns x & y for the following list objects[1,2]->x[1,2,3]->y#Initiate a list l & dictionary dl= [1,2]d[l]=42#The representation of the inside of a dictionary's collision list/bucket would look something like this (simplified)x-> ([1,2],42)#Now append 3 to the listl.append(3)>> [1,2,3]#The representation of the inside of a dictionary's collision list/bucket would change to this (simplified)x-> ([1,2,3],42)#Actual hash value was[1,2]->x#According to the collision list[1,2,3]->x#So this defies the correctness condition - for all i1, i2, if hash(i1) == hash(i2), then i1 == i2#Actual hash value was[1,2,3]->y#According to the collision list[1,2,3]->x#So this defies the correctness condition - for all i1, i2, if hash(i1) != hash(i2), then i1 != i2
Since the dictionary doesn't know when a key object is modified, such errors could only be produced at key lookup time, not at object modification time, which could make such errors quite hard to debug.
- What is
__init__.pyfor?__init__.py- Stack Overflow
- How can I swap values of variables in Python?
left, right = right, left
Pythonic way to swap variables - Stack Overflow
- What is the difference between packages and modules in Python?
Module vs Package - Stack Overflow
- Can you write multithreading applications in Python?
Yes, one can write multithreading applications in python for cases when a responsive UI is needed, I/O or network is the bottleneck. C extensions and C code can run in parallel in Python, however, only one active Python thread can run in Python. The GIL prevents making use of one CPU core or separate CPUs to run python threads in parallel.
Multithreading in Python - Stack Overflow
- Why is GIL needed?
In order to make the dynamic memory management in CPython work correctly, the GIL prevents multiple threads from running Python code at the same time. This is because CPython's dynamic memory management is not thread-safe - it can have those same problems of multiple threads accessing (or worse, disposing) the same resource at the same time. The GIL was a compromise between the two extremes of not allowing multi-threaded code, and having the dynamic memory management be very bulky and slow.
Is multithreading a myth - Stack Overflow
Multithreading vs Mulitprocessing?
Multiprocessing Pros -- Separate memory space
- Code is usually straightforward
- Takes advantage of multiple CPUs & cores
- Avoids GIL limitations for cPython
- Eliminates most needs for synchronization primitives unless if you use - shared memory (instead, it's more of a communication model for IPC)
- Child processes are interruptible/killable
- Python
multiprocessingmodule includes useful abstractions with an - interface much likethreading.Thread - A must with cPython for CPU-bound processing
Multiprocessing Cons -
- IPC a little more complicated with more overhead (communication model vs. - shared memory/objects)
- Larger memory footprint
Threading Pros -
- Lightweight - low memory footprint
- Shared memory - makes access to state from another context easier
- Allows you to easily make responsive UIs
- cPython C extension modules that properly release the GIL will run in - parallel
- Great option for I/O-bound applications
Threading Cons -
- cPython - subject to the GIL
- Not interruptible/killable
- If not following a command queue/message pump model (using the
Queuemodule)- , then manual use of synchronization primitives become a necessity (decisions are needed for the granularity of locking) - Code is usually harder to understand and to get right - the potential for - race conditions increases dramatically
What is the
__dict__attribute of an object in Python?
Basically it contains all the attributes which describe the object in question. It can be used to alter or read the attributes. Quoting from the documentation for__dict__A dictionary or other mapping object used to store an object's (writable) attributes
What is
selfkeyword used for in python?selfrepresents the current instance of a class which is used to access the properties and methods of a class.selfexplained to a beginner - Stack Overflow
The purpose of self -Stack Overfloww
- What is the
__init__function used for?
The__init__function is called a constructor, or initializer, and is automatically called when you create a new instance of a class. Within that function, the newly created object is assigned to the parameter self.
Why do we use__init__in python - Stack Overflow
- What is pickling and unpickling in python?
“Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy. Pickling (and unpickling) is alternatively known as “serialization”, “marshalling,” or “flattening”; however, to avoid confusion, the terms used here are “pickling” and “unpickling”.
Code Example - Stack Overflow
- Pickling usecases?
- Saving a program's state data to disk so that it can carry on where it left off when restarted (persistence)
- Sending python data over a TCP connection in a multi-core or distributed system (marshalling)
- Storing python objects in a database
- Converting an arbitrary python object to a string so that it can be used as a dictionary key (e.g. for caching & memoization).
Common pickling usecases - Stack Overflow
What is the output of
-12 % 10?>>>-12%108
What is the output of
-12 // 10?>>>-12//10-2
-1.2 is rounded off to -2.
Why shouldn't you make the default arguments an empty list?
A new list is created once when the function is defined, and the same list is used in each successive call.
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will have mutated that object for all future calls to the function as well.defappend_to_list(element,list_to_append=[]):list_to_append.append(element)returnlist_to_append>>>a=append_to_list(10)[10]>>>b=append_to_list(20)[10,20]
- What is the
id()function in Python?
The id() function returns a unique id for the specified object.
All objects in Python has its own unique id.
The id is assigned to the object when it is created.
The id is the object's memory address, and will be different for each time you run the program. (except for some object that has a constant unique id, like integers from -5 to 256)
- What is the
yieldkeyword used for in Python?yieldis used to create generators. If a compiler detects theyieldkeyword inside a function, that function no longer returns via thereturnstatement. Instead it immediately returns a generator object. The python function now maintains state which helps the function to resume where it left off.
What is a generator?
A generator is simply a function which returns an object on which you can call next, such that for every call it returns some value, until it raises aStopIterationexception, signaling that all values have been generated. Such an object is called an iterator. Generator is a subtype ofIterator.Normal functions return a single value using return, just like in Java. In Python, however, there is an alternative, called yield. Using yield anywhere in a function makes it a generator. Observe this code:>>>defmyGen(n):...yieldn...yieldn+1...>>>g=myGen(6)>>>next(g)6>>>next(g)7>>>next(g)Traceback (mostrecentcalllast):File"<stdin>",line1,in<module>StopIteration
As you can see, myGen(n) is a function which yields n and n + 1. Every call to next yields a single value, until all values have been yielded. for loops call next in the background, thus:
>>>forninmyGen(6):...print(n)...67
- Why use generators?
When you are calculating a large data set and are unsure whether you'll need the entire result.
When you don't want to allocate memory for the entire result at once (space).
When you don't want to wait for the entire result to be calculated (time).
Generators allow for a natural way to create infinite streams.
>>>deffib():...a,b=0,1...whileTrue:...yielda...a,b=b,a+b...>>>importitertools>>>list(itertools.islice(fib(),10))[0,1,1,2,3,5,8,13,21,34]
What can you use python generators for - Stack Overflow
Understanding generators in python -Stack Overflow
What are iterators in python? Write a custom iterator.
Iterators are objects that allow you to traverse through all the elements of a collection and return one element at a time. More specifically, we say that an iterator is an object that implements the iterator protocol.
An iterator protocol is nothing but a specific class in Python which further has the__iter__()and__next__()methods.
Python Iterators: A Step-By-Step Introduction – dbader.orgStep by Step Guide on Iterators
# A custom fibonacci iteratorclassFiborator:def__init__(self,stop=100)->None:self.stop=stopself.start_a=0self.start_b=1def__iter__(self):returnselfdef__next__(self):whileself.start_a<=self.stop:result=self.start_aself.start_a,self.start_b=self.start_b,self.start_a+self.start_breturnresultraiseStopIterationfib=Fiborator()foriinfib:print(i)
Iterable vs Iterator vs Iteration?
Aniterable is an object that has an__iter__method which returns an iterator, or which defines a__getitem__method that can take sequential indexes starting from zero (and raises anIndexErrorwhen the indexes are no longer valid). So an iterable is an object that you can get an iterator from.
Aniterator is an object with anext(Python 2) or__next__(Python 3) method.
Iterable vs Iterator vs Iteration - Stack Overflow
- What is the difference between
__iter__()and__next__()?
Iterables have an__iter__method which returns an iterator. Iterators have a__next__method which returns either their next value or raise aStopIteration
What is a context manager? How are they different from
try ... finally?
Context managers allow you to allocate and release resources precisely when you want to. This exempts the developer from managing external resources such as files, network connections and locks. Sometimes a program will retain those resources forever. This kind of issue is called a memory leak because the available memory gets reduced every time you create and open a new instance without closing it.
For example, a common problem that can arise when developers are working with databases is when a program keeps creating new connections without releasing or reusing them. In that case, the database backend can stop accepting new connections. This might require an admin to log in and manually kill those stale connections to make the database usable again.
Thewithstatement allows you to setup and teardown the instances in a safer, cleaner and reusable manner. Whereas in atry ... finallyyou still have to explicitly close the connection.The context manager object results from evaluating the
expressionafterwith. In other words,expressionmust return an object that implements the context management protocol. This protocol consists of two special methods:.__enter__()is called by thewithstatement to enter the runtime context..__exit__()is called when the execution leaves thewithcode block.
- How can you copy an object in Python? How to make a deep copy?
One can use thecopymodule to create a true copy of the object.
The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):- Ashallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- Adeep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
How does garbage collection work in python?
Reference Counting -
The main garbage collection mechanism in CPython is Reference Counts. Whenever you create an object in Python, the underlying C Object has both a Python type and a reference count.
At a very basic level, a Python object's reference count is incremented whenever the object is referenced, and it is decremented when an object is delinked. If the reference count for the object is 0, the memory for the object is released.
A few ways to increase the reference count -- Assigning an object to a variable.
- Adding an object to a data structure, such as appending to a list or adding as a property on a class instance.
- Passing the object as an argument to a function.
>>>importsys>>>a='my-string'>>>sys.getrefcount(a)2
Generational Garbage Collection -While reference counting is easy to implement and makes the life of a developer easier, it has its drawbacks. It will not clear objects with cyclical references.
A reference cycle is when a object refers to itself. The simplest example would be -
>>>a= [1,2]>>>a.append(a)
In such cases, the generational collector runs after a certain threshold is reached for it's generation and clears all the self referencing objects that are not being referenced by any other object externally.
- What are decorators in Python?
By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.
An excellent article on what are decorators -Primer on Python Decorators - Real Python
- Is python pass-by-value or pass-by-reference?
Amazing Explanation by Robert Heaton
How are lists built internally in python?
Python List Implementation - Laurent Luce
What does if
__name__ == "__main__":do?
Is Python interpreted, or compiled, or both?
How is memory managed in python?
There are two parts of memory:
- stack memory
- heap memory
The methods/method calls and the references are stored in stack memory and all the values objects are stored in a private heap.
The allocation happens on contiguous blocks of memory. We call it stack memory allocation because the allocation happens in the function call stack. The size of memory to be allocated is known to the compiler and whenever a function is called, its variables get memory allocated on the stack.
It is the memory that is only needed inside a particular function or method call. When a function is called, it is added onto the program’s call stack. Any local memory assignments such as variable initializations inside the particular functions are stored temporarily on the function call stack, where it is deleted once the function returns, and the call stack moves on to the next task. This allocation onto a contiguous block of memory is handled by the compiler using predefined routines, and developers do not need to worry about it.
Example:
deffunc():# All these variables get memory# allocated on stack`a=20b= []c=""
The memory is allocated during the execution of instructions written by programmers. Note that the name heap has nothing to do with the heap data structure. It is called heap because it is a pile of memory space available to programmers to allocated and de-allocate. The variables that are needed outside of method or function calls or are shared within multiple functions globally are stored in Heap memory.
Example:
# This memory for 10 integers# is allocated on heap.a= [0]*10
Memory Management in Python - GeeksforGeeks
What is the difference between
rangeandxrange?While
xrangehas been deprecated starting from python 3 (because range now doesxrangeused to do), the difference was thatrangereturned a static list whilexrangereturned a generator object. Hence the objects were created on the fly. Leading to lesser time and memory consumption.
- More such useful questions/answers shared byInterviewBit
How can I reload a previously imported module?
fromimportlibimportreloadimportfooifis_changed(foo):reload(foo)
What will be the output of the following code?
>>>a= [[]]*3>>>a[1].append(1)>>>print(a)[[1], [1], [1]]
Write a
timeitdecorator to measure the time of function execution -importfunctoolsfromdatetimeimportdatetimedeftimeit(func):@functools.wraps(func)defwrapper_timeit(*args,**kwargs):start=datetime.now()value=func(*args,**kwargs)end=datetime.now()-startprint(f"Finished{func.__name__} in{end}")returnvaluereturnwrapper_timeit@timeitdeftest_decorator():foriinrange(200000000):passtest_decorator()>>>Finishedtest_decoratorin0:00:03.730084
Write a decorator function that will catch errors and repeat the function execution n number of times -
defretry(num_times=3):defdecorator_retry(func):@functools.wraps(func)defwrapper_retry(*args,**kwargs):foriinrange(num_times):try:returnfunc(*args,**kwargs)exceptExceptionase:print("Retry number: ",i+1)ifi+1==num_times:print("Retry limit reached")raisereturnwrapper_retryreturndecorator_retry
We have the following code with the unknown function f(). In f(), we do not want to use a return, instead, we may want to use a generator.
forxinf(5):print(x,)
The output looks like this:
0182764
Answer -
deff(x): forninrange(x): yieldn**3foriinf(5):print(i,)
How to translate string containing binary code into a number? Write a function to do this -
defget_int(number):start=2** (len(number)-1)total=0foriinnumber:total+=int(i)*startstart=start//2returntotalprint(get_int('11111111'))
Write a function that returns a string of numbers from 0 to 100, "0123456789101112..."
foriinrange(0,100):print(i,end='')
What will be the output of the following code?
classPerson:def__init__(self,name):__name__=namedefgetAge(self):print(__name__)p=Person("John")p.getAge()# Output>>>__main__
While__name__ is a built-in variable, since we are setting it inside a function, it's scope is only limited to that function. So when we refer the variable outside of that function, the value for__name__ remains as__main__.
What is the output of the following code?
x= [[0], [1]]print(len(' '.join(list(map(str,x)))))#Output>>>x= [[0], [1]]>>>print(len(' '.join(list(map(str,x)))))7#Simplifying>>>print(' '.join(list(map(str,x)))) [0] [1]>>>print(list(map(str,x))) ['[0]','[1]']
About
Resources
Uh oh!
There was an error while loading.Please reload this page.