(Paper) Python Interview Questions And Answers Set - 3

Python Interview Questions And Answers Set - 3

 

How do you remove duplicates from a list?
If you don't mind reordering the list, sort it and then scan from the end of the list, deleting duplicates as you go:

if List:
List.sort()
last = List[-1]
for i in range(len(List)-2, -1, -1):
if last==List[i]: del List[i]
else: last=List[i]

If all elements of the list may be used as dictionary keys (i.e. they are all hash able) this is often faster

d = {}
for x in List: d[x]=x
List = d.values()

How do you make an array in Python?
Use a list:
["this", 1, "is", "an", "array"]

Lists are equivalent to C or Pascal arrays in their time complexity; the primary difference is that a Python list can contain objects of many different types.

The array module also provides methods for creating arrays of fixed types with compact representations, but they are slower to index than lists. Also note that the Numeric extensions and others define array-like structures with various characteristics as well.

To get Lisp-style linked lists, you can emulate cons cells using tuples:

lisp_list = ("like", ("this", ("example", None) ) )

If mutability is desired, you could use lists instead of tuples. Here the analogue of lisp car is lisp_list[0] and the analogue of cdr is lisp_list[1]. Only do this if you're sure you really need to, because it's usually a lot slower than using Python lists.

How do I create a multidimensional list?
You probably tried to make a multidimensional array like this:

A = [[None] * 2] * 3

This looks correct if you print it:

>>> A
[[None, None], [None, None], [None, None]]

But when you assign a value, it shows up in multiple places:

>>> A[0][0] = 5
>>> A
[[5, None], [5, None], [5, None]]

The reason is that replicating a list with * doesn't create copies, it only creates references to the existing objects. The *3 creates a list containing 3 references to the same list of length two. Changes to one row will show in all rows, which is almost certainly not what you want.

The suggested approach is to create a list of the desired length first and then fill in each element with a newly created list:

A = [None]*3
for i in range(3):
A[i] = [None] * 2

This generates a list containing 3 different lists of length two. You can also use a list comprehension:

w,h = 2,3
A = [ [None]*w for i in range(h) ]

Or, you can use an extension that provides a matrix datatype; Numeric Python is the best known.

How do I apply a method to a sequence of objects?
Use a list comprehension:

result = [obj.method() for obj in List]

More generically, you can try the following function:

def method_map(objects, method, arguments):
"""method_map([a,b], "meth", (1,2)) gives [a.meth(1,2), b.meth(1,2)]"""
nobjects = len(objects)
methods = map(getattr, objects, [method]*nobjects)
return map(apply, methods, [arguments]*nobjects)

I want to do a complicated sort: can you do a Schwartzman Transform in Python?
Yes, it's quite simple with list comprehensions.

The technique, attributed to Randal Schwartz of the Perl community, sorts the elements of a list by a metric which maps each element to its "sort value". To sort a list of strings by their uppercase values:

tmp1 = [ (x.upper(), x) for x in L ] # Schwartzman transform
tmp1.sort()
Usorted = [ x[1] for x in tmp1 ]

To sort by the integer value of a subfield extending from positions 10-15 in each string:

tmp2 = [ (int(s[10:15]), s) for s in L ] # Schwartzman transform
tmp2.sort()
Isorted = [ x[1] for x in tmp2 ]

Note that Isorted may also be computed by

def intfield(s):
return int(s[10:15])

def Icmp(s1, s2):
return cmp(intfield(s1), intfield(s2))

Isorted = L[:]
Isorted.sort(Icmp)

but since this method calls intfield() many times for each element of L, it is slower than the Schwartzman Transform.

How do I call a method defined in a base class from a derived class that overrides it?
If you're using new-style classes, use the built-in super() function:

class Derived(Base):
def meth (self):
super(Derived, self).meth()

If you're using classic classes: For a class definition such as class Derived(Base): ... you can call method meth() defined in Base (or one of Base's base classes) as Base.meth(self, arguments...). Here, Base.meth is an unbound method, so you need to provide the self argument.

How can I organize my code to make it easier to change the base class?
You could define an alias for the base class, assign the real base class to it before your class definition, and use the alias throughout your class. Then all you have to change is the value assigned to the alias. Incidentally, this trick is also handy if you want to decide dynamically (e.g. depending on availability of resources) which base class to use. Example:

BaseAlias = <real base class>
class Derived(BaseAlias):
def meth(self):
BaseAlias.meth(self)

How do I create static class data and static class methods?
Static data (in the sense of C++ or Java) is easy; static methods (again in the sense of C++ or Java) are not supported directly.

For static data, simply define a class attribute. To assign a new value to the attribute, you have to explicitly use the class name in the assignment:

class C:
count = 0 # number of times C.__init__ called

def __init__(self):
C.count = C.count + 1

def getcount(self):
return C.count # or return self.count

c.count also refers to C.count for any c such that isinstance(c, C) holds, unless overridden by c itself or by some class on the base-class search path from c.__class__ back to C.

Caution: within a method of C, an assignment like self.count = 42 creates a new and unrelated instance vrbl named "count" in self's own dict. Rebinding of a class-static data name must always specify the class whether inside a method or not:

C.count = 314

Static methods are possible when you're using new-style classes:

class C:
def static(arg1, arg2, arg3):
# No 'self' parameter!
...
static = staticmethod(static)

However, a far more straightforward way to get the effect of a static method is via a simple module-level function:

def getcount():
return C.count

If your code is structured so as to define one class (or tightly related class hierarchy) per module, this supplies the desired encapsulation.

How can I overload constructors (or methods) in Python?
This answer actually applies to all methods, but the question usually comes up first in the context of constructors.

In C++ you'd write

class C {
C() { cout << "No arguments\n"; }
C(int i) { cout << "Argument is " << i << "\n"; }
}

in Python you have to write a single constructor that catches all cases using default arguments. For example:

class C:
def __init__(self, i=None):
if i is None:
print "No arguments"
else:
print "Argument is", i


This is not entirely equivalent, but close enough in practice.

You could also try a variable-length argument list, e.g.

def __init__(self, *args):
....

The same approach works for all method definitions.

How do I find the current module name?
A module can find out its own module name by looking at the predefined global variable __name__. If this has the value '__main__', the program is running as a script. Many modules that are usually used by importing them also provide a command-line interface or a self-test, and only execute this code after checking __name__:

def main():
print 'Running test...'
...

if __name__ == '__main__':
main()
__import__('x.y.z') returns

Try:
__import__('x.y.z').y.z

For more realistic situations, you may have to do something like
m = __import__(s)
for i in s.split(".")[1:]:
m = getattr(m, i)

When I edit an imported module and reimport it, the changes don't show up. Why does this happen?
For reasons of efficiency as well as consistency, Python only reads the module file on the first time a module is imported. If it didn't, in a program consisting of many modules where each one imports the same basic module, the basic module would be parsed and re-parsed many times. To force rereading of a changed module, do this:

import modname
reload(modname)

Warning: this technique is not 100% fool-proof. In particular, modules containing statements like

from modname import some_objects

will continue to work with the old version of the imported objects. If the module contains class definitions, existing class instances will not be updated to use the new class definition. This can result in the following paradoxical behavior:

>>> import cls
>>> c = cls.C() # Create an instance of C
>>> reload(cls)
<module 'cls' from 'cls.pyc'>
>>> isinstance(c, cls.C) # isinstance is false?!?
False

The nature of the problem is made clear if you print out the class objects:

>>> c.__class__
<class cls.C at 0x7352a0>
>>> cls.C
<class cls.C at 0x4198d0>

Where is the math.py (socket.py, regex.py, etc.) source file?
There are (at least) three kinds of modules in Python:

1. modules written in Python (.py);
2. modules written in C and dynamically loaded (.dll, .pyd, .so, .sl, etc);
3. modules written in C and linked with the interpreter; to get a list of these, type:
import sys
print sys.builtin_module_names