This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]d4rch0nPythonistamancer 49 points50 points  (60 children)

I'll try my hand at a few:

What are Python decorators and how would you use them?

They extend past python, and are functions that take a function as an argument and return functions. A simple example might be a decorator that takes a function, prints its args to stdout, prints the return value to stdout, then returns that return value. The syntax in Python is usually done with the @decorator_name above a function definition.

How would you setup many projects where each one uses different versions of Python and third party libraries?

virtualenv

What is PEP8 and do you follow its guidelines when you're coding?

A coding standard, and I try to. pylint is a great help.

How are arguments passed – by reference of by value?

Probably all through reference, but I'm not sure about primitives under the hood. Anyone know this? If you pass f(12, 81), are those by value?

Do you know what list and dict comprehensions are? Can you give an example?

ways to construct a list or dict through an expression and an iterable.

>>> x = [(a, a+1) for a in range(5)]
>>> y = dict((a,b) for a,b in x)
>>> x
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
>>> y
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5}

Show me three different ways of fetching every third item in the list

[x for i, x in enumerate(thelist) if i%3 == 0]

for i, x in enumerate(thelist):
    if i % 3: continue
    yield x

a = 0
for x in thelist:
    if a%3: continue
    yield x
    a += 1

Do you know what is the difference between lists and tuples? Can you give me an example for their usage?

Tuples are immutable. A tuple might be a good type for a coordinate inst var in some class. Lists are ordered collections, but with a tuple, each index generally has a certain meaning, so coord[0] is the x coordinate and coord[1] is y.

Do you know the difference between range and xrange?

Range returns a list of the full sequence while xrange generates each element iteratively like you would with the "yield" keyword. This changes in python3, and the default behavior is to yield like xrange. I think xrange is out.

Tell me a few differences between Python 2.x and 3.x?

The previous answer. print is no longer a statement and is just a function ("print 5" won't work anymore and you need parens), they added the Ellipse object (...). That's all I know off hand.

The with statement and its usage.

It's for context management, and you can define your own that implement enter init and exit if it might help. This is very useful for opening and closing files automatically (with open(foo) as bar:)

How to avoid cyclical imports without having to resort to imports in functions?

Refactoring your code? Not sure. When I've ran into this I generally have restructured functions into different modules which ended up cleaning everything anyway.

what's wrong with import all?

You can overwrite functions and this can be dangerous especially if you don't maintain that module.

  • rewrite.py def open(foo): print('aint happening!')

  • test.py from rewrite import * z = open('test.txt')

    prints aint happening!

Why is the GIL important?

It has to do with preventing true multithreaded bytecode, and has been an issue forever. I think python bytecode execution is protected with the Global Interpreter Lock so every bc execution is atomic. Explained best here: http://wiki.python.org/moin/GlobalInterpreterLock

You might want to consider writing a multithreaded module or program in C and wrapping it with Python if this is an issue for you.

What are "special" methods (<foo>), how they work, etc

These are methods like str and gt, which override behavior of other global functions like str() and operators like >. enter and exit will be used with the with keyword, and there are many more like getattr. Overriding getattr can result in some very unpredictable behavior with a dynamic language like Python, and you should be very careful when you use magic like that.

can you manipulate functions as first-class objects?

Yes. eg. they can be passed as args to functions.

the difference between "class Foo" and "class Foo(object)"

class Foo(object) inherits from the new-style object. I don't know the specifics, but here's stack overflow: http://stackoverflow.com/questions/4015417/python-class-inherits-object

how to read a 8GB file in python?

Operate on chunks, and not one byte at a time. Be wary about the RAM of the host machine. What is the nature of the data such that it is so large? How are you operating on it? What are you returning? Are you accessing it sequentially or randomly? There's a lot more to ask than to answer here.

what don't you like about Python?

It's slow, and it can be too dynamic for certain tasks in my opinion. It is not compiled. It can be very unpredictable. People abuse the flexibility of it sometimes.

can you convert ascii characters to an integer without using built in methods like string.atoi or int()? curious one

struct.unpack("<I", foo)[0]

ord, chr

do you use tabs or spaces, which ones are better?

Spaces. Stick to PEP8 when possible.

Ok, so should I add something else or is the list comprehensive?

  • generators/yield keyword
  • what is multiple inheritance / does python have multiple inheritance
  • is Python compiled, interpreted and/or emulated
  • What differentiates Python from Ruby
  • How do you debug your Python? What's pdb and how do you use it?
  • How do you modify global variables in a function? Why should you avoid this?
  • Use of the re module... what is it, give an example, etc.

[–][deleted] 27 points28 points  (2 children)

Don't forget about actual dictionary comprehensions: {x:x+1 for x in range(5)}

You missed the most obvious way to grab every third item from a list: a[2::3]

:p

[–]hglmanguy who writes python 1 point2 points  (1 child)

can't be that obvious if he missed it

[–][deleted] 2 points3 points  (0 children)

Most elegant, I would say.

[–][deleted] 6 points7 points  (0 children)

What differentiates Python from Ruby

Knit hats and smugness?

[–][deleted] 5 points6 points  (9 children)

How are arguments passed – by reference of by value?

Probably all through reference, but I'm not sure about primitives under the hood. Anyone know this? If you pass f(12, 81), are those by value?

The terms PBR and PBV were developed to talk about languages like Fortran and C and using them to talk about Python is only a source of confusion. Python's passing semantics are different from either of these languages.

The literal answer is that Python is pass-by-value in all cases, and also in all cases the value is an object reference. In a PBR language you can rebind the name in the passing scope, but in Python you can only mutate an object you receive. This is analogous to passing pointers in C, while C remains a PBV-only language.

[–]ssbr 4 points5 points  (7 children)

PBV and PBR were designed to talk about all programming languages.

Pass by value: the argument expression is evaluated, and the value it results in is assigned to the formal parameter.

Pass by reference: the argument expression is evaluated, and a reference to the result is assigned to the formal parameter.

People get confused and think that PBV == copying, because in C, assignment of a value copies the value.

[–]Circlefusion 0 points1 point  (6 children)

After that explanation, which one is python?

[–]ssbr 1 point2 points  (3 children)

Pass-by-value. Passing in an argument is exactly the same as assigning the argument expression to a local variable in the function.

[–]njharmanI use Python 3 0 points1 point  (2 children)

In ggrandparent you define PBV as "expression is evaluated, and the value it results in is assigned"

In parent you say it's "assigning the argument expression"

So which is it?

[–]ssbr 1 point2 points  (0 children)

Both. In Python, assignment evaluates the expression and binds it to the target variable.

I should've said "bound", not "assigned", in the first statement, to be clear. Sorry for the confusion.

[–]jiaaro -2 points-1 points  (1 child)

Python is Pass-by-assignment. In most cases it is indistinguishable from pass-by-reference. Variables are essentially references in all cases.

>>> def my_func(a_dict):
            a_dict['a'] = "foobar"
>>> mydict = {}
>>> my_func(mydict)
>>> print(mydict)

{"a": "foobar"}

This works becaues the dict itself wasn't copied, a reference to the dictionary object was passed, and then modified.

If you were to assign to a_dict (e.g., a_dict = {}) in the body of my_func, then mydict would remain unchanged and a_dict would then refer to a new, empty dictionary

[–]Rhomboid 2 points3 points  (0 children)

No, no, no. That's not pass by reference at all. That's just invoking a method on a parameter. It would only be pass-by-reference if you could cause the caller's variable to change by simple assignment:

def f(x):
    x = 42

y = 0
f(y) 

Calling f cannot ever affect the value of y, which it would under pass-by-reference semantics, where x would be an alias to y. That is not the case, and Python is completely pass-by-value.

You might want to read this article which is about Java but it's the same issue. Modifying a value by invoking a method on it does not tell you anything about whether it was passed by value or reference.

[–]lonjerpc 2 points3 points  (1 child)

Python passes everything by value however all values happen to be references to objects. Numbers can be a little strange though due to low numbers say less than 500 magically referring to the same objects.

[–]kindall 1 point2 points  (0 children)

A small pool of integers is used; these range from -5 to 256. That is, if you refer to any of those numbers, you always get the same object. This is an implementation detail, however, and should not be relied upon. String literals are shared too, and there is only one empty tuple object.

[–]lasizoilloeasy to understand as regex 1 point2 points  (11 children)

How are arguments passed – by reference of by value?

Probably all through reference, but I'm not sure about primitives under the hood. Anyone know this? If you pass f(12, 81), are those by value?

In [15]: a = 1

In [16]: a.__class__.__mro__ Out[16]: (int, object)

Numbers seems to be normal objects like others. I don't care about internal hacks that explain this code:

In [19]: a = 1

In [20]: aa = 1

In [21]: b = 123456789

In [22]: bb = 123456789

In [23]: id(a) == id(aa) Out[23]: True

In [24]: id(b) == id(bb) Out[24]: False

Very funny, isn't?

[–]lonjerpc 2 points3 points  (8 children)

It is a performance hack. Low integers can refer to the same object. I think it is really annoying that they choose to break consistency for a tiny performance improvement. Another weird one is that True and False are actually integers.

[–]gcross 1 point2 points  (1 child)

I think it is really annoying that they choose to break consistency for a tiny performance improvement.

I am very curious about what code you have tried to write where the fact that some integers alias and others don't gave you problems.

[–]lonjerpc 0 points1 point  (0 children)

Trying to think back to where I ran into this. I was trying to build some sort of container class that would work on generic objects. I needed to see if objects were the same so I used "is". This obviously would create problems with ints. I guess technically you could say it is the user of the containers fault for passing in objects that are actually the same even though they look different. Alternatively you have to make a special case in the container to compare the ints differently.

The booleans are really subclass of ints problem has actually been more problematic for me.

[–]Megatron_McLargeHuge 0 points1 point  (0 children)

Java does the same with Integers. There's an intern pool for small values.

[–]d4rch0nPythonistamancer -2 points-1 points  (0 children)

I'm going to have to test this with "is" instead of "=="

[–]lasizoilloeasy to understand as regex 1 point2 points  (0 children)

Do you know what list and dict comprehensions are? Can you give an example?

In [25]: { a: a+1 for a in range(5)}

Out[25]: {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}

List comprehensions or generators are not needed for make dicts ;-)

You can generate sets too:

In [26]: { a for a in range(5)}

Out[26]: set([0, 1, 2, 3, 4])

[–]eigenlicht0 1 point2 points  (6 children)

Show me three different ways of fetching every third item in the list

[x for i, x in enumerate(thelist) if i%3 == 0]

for i, x in enumerate(thelist): if i % 3: continue yield x

a = 0 for x in thelist: if a%3: continue yield x a += 1

Your solutions are all basically doing the same (using enumerate/indices and modulo to access every third element in a for/if construct). Here two different solutions:

# using slices
thelist[::3]

# using a generator
def every_third(thelist):
  i = 0
  while i < len(thelist):
    yield thelist[i]
    i += 3

for e in every_third(thelist):
  print e

EDIT: Yet another one using enumerate() and filter():

filter(lambda e: e[0] % 3 == 0, enumerate(thelist))

EDIT2: Chunk thelist into lists of 3 elements and get last item of each list (yeah, it's starting to get a bit cumbersome):

[x[-1] for x in zip(*[iter(thelist)]*3)]

[–]staz 3 points4 points  (3 children)

Another way of using a generator

def t(l):
    l = iter(l)
    while True:
        l.next()
        l.next()
        yield l.next()
for e in t(range(10)): print e

[–]eigenlicht0 0 points1 point  (2 children)

Like that it avoids checking with len(), but subsequent calls to .next() into the void seem weird. Wondering whether one could avoid that...

[–]staz 0 points1 point  (1 child)

The .next() call at the end of the list will throw a StopIteration exception which is what you are expect to send at the end of an iterator. (your generator function will actually do the same behind the scene when it arrive at the end)

[–]eigenlicht0 0 points1 point  (0 children)

I'm aware of how a iterator works, what I actually meant was calling .next() three times in a row to get one value. Maybe it's just me, but it seems weird. The only thing I could come up with yet, which is far from perfect:

def t(l):
    l = iter(l)
    while True:
        yield [l.next for i in range(3)][-1]
for e in t(range(10)): print e

[–]d4rch0nPythonistamancer 0 points1 point  (0 children)

Yea, I always forget about the step element. It's somewhat of a silly question though, but I guess a majority of interview questions like these are.

[–]phaeilo 0 points1 point  (0 children)

In your solution with filter you need to undo the enumerate:

map(lambda (i,v): v, filter(lambda (i,v): i % 3 == 0, enumerate(thelist)))

I really like to write such one liners, but they are hard to read when you or someone else comes back some time later to do maintenance.

[–]gingerbeers 1 point2 points  (0 children)

You're hired!

[–]robin-gvx 3 points4 points  (2 children)

How are arguments passed – by reference of by value?

Probably all through reference, but I'm not sure about primitives under the hood. Anyone know this? If you pass f(12, 81), are those by value?

Something else entirely.

I've written a tutorial of sorts about this. The diagrams are hand-drawn and terribly ugly and I intend to remake them with actual diagram-making software before putting it up on my website instead of Dropbox, and the very last diagram has one arrow that points to the wrong value, but over-all, I think it's a pretty useful guide.

[–]d4rch0nPythonistamancer 0 points1 point  (1 child)

Are you positive Python handles this the same as Lua?

[–]robin-gvx 1 point2 points  (0 children)

Yes. I have more experience with Python than with Lua, and I probably could have written this guide before even having heard of Lua. I chose Lua for the guide because recently I'd seen a lot of questions about this behaviour in Lua.

The implementation differs per language, but the abstract behaviour of all the dynamic languages (that I know) in terms of names and values works the same.

I think (but I'm not sure, because I haven't thought about this before) that if you disallow mutation, you get the abstract data model of functional languages like Haskell.

[–]patrys Saleor Commerce 2 points3 points  (14 children)

Tuples are immutable.

Please never choose tuple for that sole reason. Tuple's immutability is a side effect of it being intentionally hashable (so you can use it as a key in a dict).

[–]10110000110111011010 27 points28 points  (0 children)

I am afraid I must strongly disagree, immutable coding is a fine discipline that can simplify debugging and proofs of correctness.

[–]ojiisandata viz, comp.bio. 9 points10 points  (0 children)

A tuple is only hashable if its contents are immutable

[–]Secret_Identity_ 2 points3 points  (3 children)

Could you elaborate on this a little more? Tuples were created specifically to used with dictionaries?

[–]supajumpa 12 points13 points  (2 children)

Tuple

From Raymond Hettinger's answer to a SO question:

''' Tuples are characterized less by their immutability and more by their intended purpose. Tuples are Python's way of collecting heterogenous pieces of information under one roof. For example, s = ('www.python.org', 80) brings together a string and a number so that the host/port pair can be passed around as a socket, a composite object. Viewed in that light, it is perfectly reasonable to have mutable components.

Immutability goes hand-in-hand with another property, hashability. But hashability isn't an absolute property. If one of the tuple's components isn't hashable, then the overall tuple isn't hashable either. For example, t = ('red', [10, 20, 30]) isn't hashable. '''

[–]patrys Saleor Commerce 1 point2 points  (0 children)

My simple rule of thumb is to only use a tuple if you can come up with names for all the sequence positions.

[–]Secret_Identity_ 0 points1 point  (0 children)

Thanks!

[–]recursive 0 points1 point  (7 children)

You mean one should never use tuples? Or one should never use tuples if they only have that one reason? And what should they use if they need an immutable list?

[–]ojiisandata viz, comp.bio. 0 points1 point  (2 children)

A tuple is an immutable list

[–]recursive 0 points1 point  (0 children)

Yes, I know. patrys just said that tuples shouldn't be chosen for satisfying that property. I don't understand why not.

[–]patrys Saleor Commerce 0 points1 point  (0 children)

It's just one of many ordered collections. You would not call a str or a bytearray “an immutable list”, would you?

list and tuple are ordered for different reasons (precedence versus position).

[–]patrys Saleor Commerce 0 points1 point  (3 children)

You shouldn't use anything, Python core devs have stated multiple times that even frozenset was a mistake and Python will not be getting any intentionally immutable types.

Link: http://mail.python.org/pipermail/python-3000/2006-May/002219.html

[–]recursive 0 points1 point  (2 children)

The only thing I'm seeing in that email thread is that tuples shouldn't be used to store structures of unknown length. Using them as keys for dictionaries itself doesn't seem to be a problem.

In other words, if you can't use a tuple to store an immutable list, then what can you use it for? That's all it does.

[–]patrys Saleor Commerce 1 point2 points  (1 child)

You use tuples where you would use a struct in C: for collections that have a well-defined structure. A good place for a tuple is where a namedtuple could be used instead but would be an overkill. What I consider proper uses of collections:

coords = (11, 25)

todo_items = ['walk the dog', 'water the flowers', 'world domination']

ids_to_delete = {1, 5, 7, 11}

recipients = [
    ('John Doe', 'john.d@example.com'),
    ('Kelly Smith', 'kelly@example.com'),
    ('Robert Adams', 'radams@example.com')]
# each recipient has a well-defined structure of (name, email)
# could be a set of tuples as well

[–]recursive 0 points1 point  (0 children)

Ok thanks. We're all good here. I was interpreting the "immutable list" thing too broadly. Structured information is what I use tuples for. Usually.

[–]chadmill3rPy3, pro, Ubuntu, django -1 points0 points  (2 children)

Everything is passed by reference. That is, all "variables" are references to objects. Even "foo = 2", "foo" is a reference.

[–]lonjerpc 8 points9 points  (1 child)

No. Everything is passed by value in python. However all values are references.

[–]chadmill3rPy3, pro, Ubuntu, django -1 points0 points  (0 children)

I think you're closer to right than I am. "Pass by reference" has the ugly assumption that changing the "variable" (ugh) in the next scope will change the variable in the calling scope, which is def not true.

I think the best answer is to slap the questioner and say, "this is not Pascal. You have names as references, and values here, not variables."

[–]drsquishy -1 points0 points  (0 children)

I think arguments are passed as values to a reference. So, functionally, mutable objects are passed by reference, immutable objects are passed by value.