Basic Python Interview Questions
Q1. What is the difference between list and tuples in Python?
How is memory managed in Python?
Ans: Memory is managed in Python in the following ways:
- Memory management in python is managed by Python private heap space. All Python objects and data structures are located in a private heap. The programmer does not have access to this private heap. The python interpreter takes care of this instead.
- The allocation of heap space for Python objects is done by Python’s memory manager. The core API gives access to some tools for the programmer to code.
- Python also has an inbuilt garbage collector, which recycles all the unused memory and so that it can be made available to the heap space.
What is type conversion in Python?
Ans: Type conversion refers to the conversion of one data type iinto another.
int() – converts any data type into integer type
float() – converts any data type into float type
ord() – converts characters into integer
hex() – converts integers to hexadecimal
oct() – converts integer to octal
tuple() – This function is used to convert to a tuple.
set() – This function returns the type after converting to set.
list() – This function is used to convert any data type to a list type.
dict() – This function is used to convert a tuple of order (key,value) into a dictionary.
str() – Used to convert integer into a string.
complex(real,imag) – This functionconverts real numbers to complex(real,imag) number.
What is the difference between Python Arrays and lists?
Ans: Arrays and lists, in Python, have the same way of storing data. But, arrays can hold only a single data type elements whereas lists can hold any data type elements.
Example:
1 2 3 4 5 |
|
Output:
array(‘i’, [1, 2, 3, 4]) [1, ‘abc’, 1.2]
What are functions in Python?
Ans: A function is a block of code which is executed only when it is called. To define a Python function, the def keyword is used.
Example:
1 2 3 |
|
Output: Hi, Welcome to India
What is __init__?
Ans: __init__ is a method or constructor in Python. This method is automatically called to allocate memory when a new object/ instance of a class is created. All classes have the __init__ method.
Here is an example of how to use it.
1 2 3 4 5 6 7 8 9 10 11 |
|
Output:
XYZ
23
20000
What is a lambda function?
Ans: An anonymous function is known as a lambda function. This function can have any number of parameters but, can have just one statement.
Example:
1 2 |
|
Output: 11
Lambda is an anonymous function in Python, that can accept any number of arguments, but can only have a single expression. It is generally used in situations requiring an anonymous function for a short time period. Lambda functions can be used in either of the two ways:
- Assigning lambda functions to a variable
· mul = lambda a, b : a * b
· print(mul(2, 5)) # output => 10
- Wrapping lambda functions inside another function
· def myWrapper(n):
· return lambda a : a * n
·
· mulFive = myWrapper(5)
· print(mulFive(2)) # output => 10
What is self in Python?
Ans: Self is an instance or an object of a class. In Python, this is explicitly included as the first parameter. However, this is not the case in Java where it’s optional. It helps to differentiate between the methods and attributes of a class with local variables.
The self variable in the init method refers to the newly created object while in other methods, it refers to the object whose method was called.
How does break, continue and pass work?
Break |
Allows loop termination when some condition is met and the control is transferred to the next statement. |
Continue |
Allows skipping some part of a loop when some specific condition is met, and the control is transferred to the beginning of the loop |
Pass |
Used when you need some block of code syntactically, but you want to skip its execution. This is basically a null operation. Nothing happens when this is executed. |
pat = [1, 3, 2, 1, 2, 3, 1, 0, 1, 3]
for p in pat:
pass
if (p == 0):
current = p
break
elif (p % 2 == 0):
continue
print(p) # output => 1 3 1 3 1
print(current) # output => 0
The pass keyword represents a null operation in Python. It is generally used for the purpose of filling up empty blocks of code which may execute during runtime but has yet to be written. Without the pass statement in the following code, we may run into some errors during code execution.
def myEmptyFunc():
# do nothing
pass
myEmptyFunc() # nothing happens
## Without the pass keyword
# File "<stdin>", line 3
# IndentationError: expected an indented block
How can you randomize the items of a list in place in Python?
Ans: Consider the example shown below:
1 2 3 4 |
|
The output of the following code is as below.
['Flying', 'Keep', 'Blue', 'High', 'The', 'Flag']
How can you generate random numbers in Python?
Ans: Random module is the standard module that is used to generate a random number. The method is defined as:
1 2 |
import random random.random |
The statement random.random() method return the floating point number that is in the range of [0, 1). The function generates random float numbers. The methods that are used with the random class are the bound methods of the hidden instances. The instances of the Random can be done to show the multi-threading programs that creates a different instance of individual threads. The other random generators that are used in this are:
- randrange(a, b): it chooses an integer and define the range in-between [a, b). It returns the elements by selecting it randomly from the range that is specified. It doesn’t build a range object.
- uniform(a, b): it chooses a floating point number that is defined in the range of [a,b).Iyt returns the floating point number
- normalvariate(mean, sdev): it is used for the normal distribution where the mu is a mean and the sdev is a sigma that is used for standard deviation.
- The Random class that is used and instantiated creates independent multiple random number generators.
What is the difference between range & xrange?
Ans: For the most part, xrange and range are the exact same in terms of functionality. They both provide a way to generate a list of integers for you to use, however you please. The only difference is that range returns a Python list object and x range returns an xrange object.
This means that xrange doesn’t actually generate a static list at run-time like range does. It creates the values as you need them with a special technique called yielding. This technique is used with a type of object known as generators. That means that if you have a really gigantic range you’d like to generate a list for, say one billion, xrange is the function to use.
This is especially true if you have a really memory sensitive system such as a cell phone that you are working with, as range will use as much memory as it can to create your array of integers, which can result in a Memory Error and crash your program. It’s a memory hungry beast.
xrange() and range() are quite similar in terms of functionality. They both generate a sequence of integers, with the only difference that range() returns a Python list, whereas, xrange() returns an xrange object.
So how does that make a difference? It sure does, because unlike range(), xrange() doesn't generate a static list, it creates the value on the go. This technique is commonly used with an object type generators and has been termed as "yielding".
Yielding is crucial in applications where memory is a constraint. Creating a static list as in range() can lead to a Memory Error in such conditions, while, xrange() can handle it optimally by using just enough memory for the generator (significantly less in comparison).
for i in xrange(10): # numbers from o to 9
print i # output => 0 1 2 3 4 5 6 7 8 9
for i in xrange(1,10): # numbers from 1 to 9
print i # output => 1 2 3 4 5 6 7 8 9
for i in xrange(1, 10, 2): # skip by two for next
print i # output => 1 3 5 7 9
Note: xrange has been deprecated as of Python 3.x. Now range does exactly the same what xrange used to do in Python 2.x, since it was way better to use xrange() than the original range() function in Python 2.x.
## generate fibonacci numbers upto n
def fib(n):
p, q = 0, 1
while(p < n):
yield p
p, q = q, p + q
x = fib(10) # create generator object
## iterating using __next__(), for Python2, use next()
x.__next__() # output => 0
x.__next__() # output => 1
x.__next__() # output => 1
x.__next__() # output => 2
x.__next__() # output => 3
x.__next__() # output => 5
x.__next__() # output => 8
x.__next__() # error
## iterating using loop
for i in fib(10):
print(i) # output => 0 1 1 2 3 5 8
How will you capitalize the first letter of string?
Ans: In Python, the capitalize() method capitalizes the first letter of a string. If the string already consists of a capital letter at the beginning, then, it returns the original string.
How will you convert a string to all lowercase?
Ans: To convert a string to lowercase, lower() function can be used.
Example:
1 2 |
|
Output: abcd
What is a dictionary in Python?
Ans: The built-in datatypes in Python is called dictionary. It defines one-to-one relationship between keys and values. Dictionaries contain pair of keys and their corresponding values. Dictionaries are indexed by keys.
Let’s take an example:
The following example contains some keys. Country, Capital & PM. Their corresponding values are India, Delhi and Modi respectively.
1 |
|
1 |
|
India
1 |
|
Delhi
1 |
|
Modi
What does this mean: *args, **kwargs? And why would we use it?
Ans: We use *args when we aren’t sure how many arguments are going to be passed to a function, or if we want to pass a stored list or tuple of arguments to a function. **kwargs is used when we don’t know how many keyword arguments will be passed to a function, or it can be used to pass the values of a dictionary as keyword arguments. The identifiers args and kwargs are a convention, you could also use *bob and **billy but that would not be wise.
*args
- *args is a special syntax used in function definition to pass variable-length argument.
- “*” means variable length and “args” is the name used by convention. You can use any other.
def multiply(a, b, *argv):
mul = a * b
for num in argv:
mul *= num
return mul
print(multiply(1, 2, 3, 4, 5)) #output: 120
**kwargs
- **kwargs is a special syntax used in function definition to pass variable-length keyworded argument.
- Here, also, “kwargs” is used just by convention. You can use any other name.
- Keyworded argument means a variable which has a name when passed to a function.
- It is actually a dictionary of variable name and its value.
def tellArguments(**kwargs):
for key, value in kwargs.items():
print(key + ": " + value)
tellArguments(arg1 = "argument 1", arg2 = "argument 2", arg3 = "argument 3")
#output:
# arg1: argument 1
# arg2: argument 2
# arg3: argument 3
Explain split(), sub(), subn() methods of “re” module in Python.
Ans: To modify the strings, Python’s “re” module is providing 3 methods. They are:
- split() – uses a regex pattern to “split” a given string into a list.
- sub() – finds all substrings where the regex pattern matches and then replace them with a different string
- subn() – it is similar to sub() and also returns the new string along with the no. of replacements.
What advantages do NumPy arrays offer over (nested) Python lists?
Ans:
- Python’s lists are efficient general-purpose containers. They support (fairly) efficient insertion, deletion, appending, and concatenation, and Python’s list comprehensions make them easy to construct and manipulate.
- They have certain limitations: they don’t support “vectorized” operations like elementwise addition and multiplication, and the fact that they can contain objects of differing types mean that Python must store type information for every element, and must execute type dispatching code when operating on each element.
- NumPy is not just more efficient; it is also more convenient. You get a lot of vector and matrix operations for free, which sometimes allow one to avoid unnecessary work. And they are also efficiently implemented.
- NumPy array is faster and You get a lot built in with NumPy, FFTs, convolutions, fast searching, basic statistics, linear algebra, histograms, etc.
How to add values to a python array?
Ans: Elements can be added to an array using the append(), extend() and the insert (i,x) functions.
Example:
1 2 3 4 5 6 7 |
|
Output:
array(‘d’, [1.1, 2.1, 3.1, 3.4])
array(‘d’, [1.1, 2.1, 3.1, 3.4, 4.5, 6.3, 6.8])
array(‘d’, [1.1, 2.1, 3.8, 3.1, 3.4, 4.5, 6.3, 6.8])
How to remove values to a python array?
Ans: Array elements can be removed using pop() or remove() method. The difference between these two functions is that the former returns the deleted value whereas the latter does not.
Example:
1 2 3 4 5 |
|
Output:
4.6
3.1
array(‘d’, [2.2, 3.8, 3.7, 1.2])
What is the difference between deep and shallow copy?
Ans: Shallow copy is used when a new instance type gets created and it keeps the values that are copied in the new instance. Shallow copy is used to copy the reference pointers just like it copies the values. These references point to the original objects and the changes made in any member of the class will also affect the original copy of it. Shallow copy allows faster execution of the program and it depends on the size of the data that is used.
Deep copy is used to store the values that are already copied. Deep copy doesn’t copy the reference pointers to the objects. It makes the reference to an object and the new object that is pointed by some other object gets stored. The changes made in the original copy won’t affect any other copy that uses the object. Deep copy makes execution of the program slower due to making certain copies for each object that is been called.
How do you copy an object in Python?
In Python, the assignment statement (= operator) does not copy objects. Instead, it creates a binding between the existing object and the target variable name. To create copies of an object in Python, we need to use the copy module. Moreover, there are two ways of creating copies for the given object using the copy module -
- Shallow Copy is a bit-wise copy of an object. The copied object created has an exact copy of the values in the original object. If either of the values are references to other objects, just the reference addresses for the same are copied.
- Deep Copy copies all values recursively from source to target object, i.e. it even duplicates the objects referenced by the source object.
from copy import copy, deepcopy
list_1 = [1, 2, [3, 5], 4]
## shallow copy
list_2 = copy(list_1)
list_2[3] = 7
list_2[2].append(6)
list_2 # output => [1, 2, [3, 5, 6], 7]
list_1 # output => [1, 2, [3, 5, 6], 4]
## deep copy
list_3 = deepcopy(list_1)
list_3[3] = 8
list_3[2].append(7)
list_3 # output => [1, 2, [3, 5, 6, 7], 8]
list_1 # output => [1, 2, [3, 5, 6], 4]
How is Multithreading achieved in Python?
Ans:
- Python has a multi-threading package but if you want to multi-thread to speed your code up, then it’s usually not a good idea to use it.
- Python has a construct called the Global Interpreter Lock (GIL). The GIL makes sure that only one of your ‘threads’ can execute at any one time. A thread acquires the GIL, does a little work, then passes the GIL onto the next thread.
- This happens very quickly so to the human eye it may seem like your threads are executing in parallel, but they are really just taking turns using the same CPU core.
- All this GIL passing adds overhead to execution. This means that if you want to make your code run faster then using the threading package often isn’t a good idea.
Explain Inheritance in Python with an example.
Ans: Inheritance allows One class to gain all the members(say attributes and methods) of another class. Inheritance provides code reusability, makes it easier to create and maintain an application. The class from which we are inheriting is called super-class and the class that is inherited is called a derived / child class.
They are different types of inheritance supported by Python:
- Single Inheritance – where a derived class acquires the members of a single super class.
- Multi-level inheritance – a derived class d1 in inherited from base class base1, and d2 are inherited from base2.
- Hierarchical inheritance – from one base class you can inherit any number of child classes
- Multiple inheritance – a derived class is inherited from more than one base class.
How are classes created in Python?
Ans: Class in Python is created using the class keyword.
Example:
1 2 3 4 5 |
|
Output: abc
What is Polymorphism in Python?
Ans: Polymorphism means the ability to take multiple forms. So, for instance, if the parent class has a method named ABC then the child class also can have a method with the same name ABC having its own parameters and variables. Python allows polymorphism.
Define encapsulation in Python?
Ans: Encapsulation means binding the code and the data together. A Python class in an example of encapsulation.
How do you do data abstraction in Python?
Ans: Data Abstraction is providing only the required details and hiding the implementation from the world. It can be achieved in Python by using interfaces and abstract classes
How to create an empty class in Python?
Ans: An empty class is a class that does not have any code defined within its block. It can be created using the pass keyword. However, you can create objects of this class outside the class itself. IN PYTHON THE PASS command does nothing when its executed. it’s a null statement.
For example-
1 2 3 4 5 |
|
Output:
Name = xyz
What is map function in Python?
Ans: map function executes the function given as the first argument on all the elements of the iterable given as the second argument. If the function given takes in more than 1 arguments, then many iterables are given
Is python numpy better than lists?
Ans: We use python numpy array instead of a list because of the below three reasons:
- Less Memory
- Fast
- Convenient
What is Scope in Python?
Every object in Python functions within a scope. A scope is a block of code where an object in Python remains relevant. Namespaces uniquely identify all the objects inside a program. However, these namespaces also have a scope defined for them where you could use their objects without any prefix. A few examples of scope created during code execution in Python are as follows:
- A local scope refers to the local objects available in the current function.
- A global scope refers to the objects available throught the code execution since their inception.
- A module-level scope refers to the global objects of the current module accessible in the program.
- An outermost scope refers to all the built-in names callable in the program. The objects in this scope are searched last to find the name referenced.
What is Scope Resolution in Python?
Sometimes objects within the same scope have the same name but function differently. In such cases, scope resolution comes into play in Python automatically. A few examples of such behaviour are:
- Python modules namely 'math' and 'cmath' have a lot of functions that are common to both of them - log10(), acos(), exp() etc. To resolve this amiguity, it is necessary to prefix them with their respective module, like math.exp() and cmath.exp().
- Consider the code below, an object temp has been initialized to 10 globally and then to 20 on function call. However, the function call didn't change the value of the temp globally. Here, we can observe that Python draws a clear line between global and local variables treating both their namespaces as separate identities.
temp = 10 # global-scope variable
def func():
temp = 20 # local-scope variable
print(temp)
print(temp) # output => 10
func() # output => 20
print(temp) # output => 10
This behaviour can be overriden using the global keyword inside the function, as shown in the following example:
temp = 10 # global-scope variable
def func():
global temp
temp = 20 # local-scope variable
print(temp)
print(temp) # output => 10
func() # output => 20
print(temp) # output => 20
What are lists and tuples? What is the key difference between the two?
Lists and Tuples are both sequence data types that can
store a collection of objects in Python. The objects stored in both sequences
can have different data types. Lists are represented with square
brackets ['sara', 6, 0.19]
,
while tuples are represented with parantheses ('ansh', 5, 0.97)
.
But what is the real difference between the two? The key difference between the
two is that while lists are mutable, tuples on the other hand are
immutable objects. This means that lists can be modified, appended or
sliced on-the-go but tuples remain constant and cannot be modified in any
manner. You can run the following example on Python IDLE to confirm the
difference:
my_tuple = ('sara', 6, 5, 0.97)
my_list = ['sara', 6, 5, 0.97]
print(my_tuple[0]) # output => 'sara'
print(my_list[0]) # output => 'sara'
my_tuple[0] = 'ansh' # modifying tuple => throws an error
my_list[0] = 'ansh' # modifying list => list modified
print(my_tuple[0]) # output => 'sara'
print(my_list[0]) # output => 'ansh'
What are Dict and List comprehensions?
Python comprehensions, like decorators, are syntactic sugar constructs that help build altered and filtered lists, dictionaries or sets from a given list, dictionary or set. Using comprehensions, saves a lot of time and code that might be considerably more verbose (containing more lines of code). Let's check out some examples, where comprehensions can be truly beneficial:
- Performing mathematical operations on the entire list
· my_list = [2, 3, 5, 7, 11]
·
· squared_list = [x**2 for x in my_list] # list comprehension
· # output => [4 , 9 , 25 , 49 , 121]
·
· squared_dict = {x:x**2 for x in my_list} # dict comprehension
· # output => {11: 121, 2: 4 , 3: 9 , 5: 25 , 7: 49}
- Performing conditional filtering operations on the entire list
· my_list = [2, 3, 5, 7, 11]
·
· squared_list = [x**2 for x in my_list if x%2 != 0] # list comprehension
· # output => [9 , 25 , 49 , 121]
·
· squared_dict = {x:x**2 for x in my_list if x%2 != 0} # dict comprehension
· # output => {11: 121, 3: 9 , 5: 25 , 7: 49}
- Combining multiple lists into one
Comprehensions allow for multiple iterators and hence, can be used to combine multiple lists into one.
· a = [1, 2, 3]
· b = [7, 8, 9]
·
· [(x + y) for (x,y) in zip(a,b)] # parallel iterators
· # output => [8, 10, 12]
·
· [(x,y) for x in a for y in b] # nested iterators
· # output => [(1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (2, 9), (3, 7), (3, 8), (3, 9)]
- Flattening a multi-dimensional list
A similar approach of nested iterators (as above) can be applied to flatten a multi-dimensional list or work upon its inner elements.
· my_list = [[10,20,30],[40,50,60],[70,80,90]]
·
· flattened = [x for temp in my_list for x in temp]
· # output => [10, 20, 30, 40, 50, 60, 70, 80, 90]
What is slicing in Python?
- As the name suggests, ‘slicing’ is taking parts of.
- Syntax for slicing is [start : stop : step]
- start is the starting index from where to slice a list or tuple
- stop is the ending index or where to sop.
- step is the number of steps to jump.
- Default value for start is 0, stop is number of items, step is 1.
- Slicing can be done on strings, arrays, lists, and tuples.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(numbers[1 : : 2]) #output : [2, 4, 6, 8, 10]
Explain split() and join() functions in Python?
- You can use split() function to split a string based on a delimiter to a list of strings.
- You can use join() function to join a list of strings based on a delimiter to give a single string.
string = "This is a string."
string_list = string.split(' ') #delimiter is ‘space’ character or ‘ ‘
print(string_list) #output: ['This', 'is', 'a', 'string.']
print(' '.join(string_list)) #output: This is a string.
What is Python's parameter passing mechanism?
There are two parameters passing mechanism in Python:
- Pass by references
- Pass by value
By default, all the parameters (arguments) are passed "by reference" to the functions. Thus, if you change the value of the parameter within a function, the change is reflected in the calling function as well. It indicates the original variable. For example, if a variable is declared as a = 10, and passed to a function where it?s value is modified to a = 20. Both the variables denote to the same value.
The pass by value is that whenever we pass the arguments to the function only values pass to the function, no reference passes to the function. It makes it immutable that means not changeable. Both variables hold the different values, and original value persists even after modifying in the function.
Python has a default argument concept which helps to call a method using an arbitrary number of arguments.
How to overload constructors or methods in Python?
Python's constructor: _init__ () is the first method of a class. Whenever we try to instantiate an object __init__() is automatically invoked by python to initialize members of an object. We can't overload constructors or methods in Python. It shows an error if we try to overload.
- class student:
- def __init__(self,name):
- self.name = name
- def __init__(self, name, email):
- self.name = name
- self.email = email
- # This line will generate an error
- #st = student("rahul")
- # This line will call the second constructor
- st = student("rahul", "rahul@gmail.com")
- print(st.name)
- Output:
- rahul
No comments:
Post a Comment