Tricky Areas in Python

P

PyPK

What possible tricky areas/questions could be asked in Python based
Technical Interviews?
 
?

=?ISO-8859-1?Q?Gerhard_H=E4ring?=

PyPK said:
What possible tricky areas/questions could be asked in Python based
Technical Interviews?

I would try to check if the applicant understands the Python data model:
http://docs.python.org/ref/objects.html Because I thinkt that's
fundamental to understanding the Python language and understanding
complexity of operations.

-- Gerhard
 
P

PyPK

hmm Thats one thing. Also I was thinking of something like benefites of
python over other languages. Probably that coould be one ?
 
C

Chris Curvey

I usually start by asking how you make variables "private" within
classes. That seems to tell me if they understand something about the
design of the language and it's a quick filter to tell if they know
something about the syntax.

The other question that I use is asking about 3rd party libraries that
they have found useful. That can lead into some good questions about
what they like about those libraries and what they dislike. That
question helps me understand whether they've thought at all about how
to design in Python.

If I can't get a good conversation started with either of those, I'll
ask what they don't like about Python, to see if they've actually used
it to solve a real problem, or if they've just read the tutorial.

As always, the best interview questions are open-ended, and give the
candidate some room to really show their stuff (or give them enough
rope to hang themselves).
 
A

Alex Martelli

PyPK said:
What possible tricky areas/questions could be asked in Python based
Technical Interviews?

I like to present code that seems like it should work, but has some kind
of relatively subtle problem, either of correctness in some corner case,
or of performance, etc -- and I ask them what they would say if they
were to code-review that code, or how they would help a student who came
to them with that code and complaints about it not working, &c.

This tells me whether they have real-world Python experience, and how
deep, or whether they've carefully studied the appropriate areas of
"Python in a Nutshell" and the Cookbook (and I'm biased enough to think
that the second kind of preparation is almost as good as the first
kind...;-).

Not sure whether you think this count as "tricky"... they're typically
problems that do come up in the real world, from (e.g.):
for string_piece in lots_of_pieces:
bigstring += string_piece
(a typical performance-trap) to
for item in somelist:
if isbad(item):
somelist.remove(item)
(with issues of BOTH correctness and performance), to
class Sic:
def getFoo(self): ...
def setFoo(self): ...
foo = property(getFoo, setFoo)
to
class Base(object)
def getFoo(self): ...
def setFoo(self): ...
foo = property(getFoo, setFoo)

class Derived(Base):
def getFoo(self): ....

and so on, and so forth. If a candidate makes short work of a couple of
these, and I've been asked to focus my part of the interview solely on
Python coding, I may branch out into more advanced stuff such as asking
for an example use case for a closure, a custom descriptor, or an import
hook, for example -- those are the cases in which I'm trying to decide
if, on a scale of 1 to 5, the candidate's Python competence is about 4
or well over 4 (I would not consider having no idea of why one might
want to code a custom descriptor to be at all "disqualifying" -- it
would just mean I'd rate the candidate 4 out of five, instead of 4.5 or
more, for Python coding competence).


Alex
 
A

Andrew Durdin

I may branch out into more advanced stuff such as asking
for an example use case for a closure, a custom descriptor, or an import
hook, for example

Isn't that approaching things from the wrong angle? You're asking them
to synthesise a problem for a given solution, rather than analyse a
problem to determine an appropriate solution. Asking questions like
these tests memory more than competence -- for example, if you ask me
of a use case for a closure, the only answer I could give would be to
remember a problem I'd solved in the past using one.

Andrew
 
A

Alex Martelli

Andrew Durdin said:
Isn't that approaching things from the wrong angle? You're asking them
to synthesise a problem for a given solution, rather than analyse a
problem to determine an appropriate solution. Asking questions like
these tests memory more than competence -- for example, if you ask me
of a use case for a closure, the only answer I could give would be to
remember a problem I'd solved in the past using one.

And why do you think that would be wrong? If you've used closures, you
know what you've used them for, and (I would hope) why. If you've never
used them, you're welcome to answer "I have no idea why anybody would
wanna use THAT crazy thing for" (I always give points for honesty;-), or
else try to bluff your way through (sorry, no points for chutzpah!-).

I don't know of any issue that could be solved ONLY by a closure (we
didn't have closures in 1.5.2 yet we made out excellently well
anyhow;-), after all. The point is, does the candidate really
understand closures (ideally by practical experience)? Within the
limited confines of a less-than-an-hour interview (which is what we
normally use -- several interviewers, but no more than about 45 minutes
each, with different focus for each interviewer) I believe that asking
for use cases is a perfectly good way to gauge if a candidate fully
understands (ideally by experience) a certain language feature.

It's not just Python, btw. When I'm asked to focus on C++ skills, I
will similarly ask, e.g., what a use case would be for virtual
inheritance, say. How ELSE would you gauge, within that very limited
time-span, a candidate's grasp of some advanced language feechur?-)


Alex
 
B

bruno modulix

PyPK said:
hmm Thats one thing. Also I was thinking of something like benefites of
python over other languages.

That's fairly context-dependant *and* subjective.
 
S

Steven D'Aprano

Alex said:
I like to present code that seems like it should work, but has some kind
of relatively subtle problem, either of correctness in some corner case,
or of performance, etc -- and I ask them what they would say if they
were to code-review that code, or how they would help a student who came
to them with that code and complaints about it not working, &c.
[snip]

Not sure whether you think this count as "tricky"... they're typically
problems that do come up in the real world, from (e.g.):
for string_piece in lots_of_pieces:
bigstring += string_piece
(a typical performance-trap) to
for item in somelist:
if isbad(item):
somelist.remove(item)
(with issues of BOTH correctness and performance), to

Those two are easy. However, and this is where I show
my hard-won ignorance, and admit that I don't see the
problem with the property examples:
class Sic:
def getFoo(self): ...
def setFoo(self): ...
foo = property(getFoo, setFoo)
to
class Base(object)
def getFoo(self): ...
def setFoo(self): ...
foo = property(getFoo, setFoo)

class Derived(Base):
def getFoo(self): ....

Unless the answer is "Why are you using setters and
getters anyway? This isn't Java you know."

Oh wait! Yes I do... the setter doesn't actually take
an argument to set the property too. Is that it, or
have a missed a cunningly hidden deeper problem?
 
K

Kent Johnson

Steven said:
Alex Martelli wrote:
Those two are easy. However, and this is where I show my hard-won
ignorance, and admit that I don't see the problem with the property
examples:



Unless the answer is "Why are you using setters and getters anyway? This
isn't Java you know."

Oh wait! Yes I do... the setter doesn't actually take an argument to set
the property too. Is that it, or have a missed a cunningly hidden deeper
problem?

Derived.getFoo() will not override the use of Base.getFoo() to access the attribute foo.

Kent
 
F

Fredrik Lundh

Steven said:
Those two are easy. However, and this is where I show
my hard-won ignorance, and admit that I don't see the
problem with the property examples:

the property call in Base binds to the Base.getFoo and Base.setFoo method
*objects*, not the names, so overriding getFoo in Derived won't affect the foo
property.

to get proper dispatching for accessors, you need to add an extra layer:

def getFoo(self): ...
def setFoo(self, ...): ...
def getFooDispatcher(self): self.getFoo() # use normal lookup
def setFooDispatcher(self, ...): self.setFoo(...) # use normal lookup
foo = property(getFooDispatcher, setFooDispatcher)

this gotcha is the motivation for this proposal:

http://article.gmane.org/gmane.comp.python.devel/72348

(see that thread for more on this topic)

</F>
 
A

Alex Martelli

Steven D'Aprano said:
my hard-won ignorance, and admit that I don't see the
problem with the property examples:

Sorry for skipping the 2nd argument to setFoo, that was accidental in my
post. The problem here is: class Sic is "classic" ("legacy",
"old-style") so property won't really work for it (the setter will NOT
trigger when you assign to s.foo and s is an instance of Sic).
Unless the answer is "Why are you using setters and
getters anyway? This isn't Java you know."

Nope, that's not a problem -- presumably the "..." bodies DO something
useful, and they do get nicely dressed in attribute syntax. The
problem, as others have indicated, is that overriding doesn't work as
one might expect -- the solution, in Python 2.4 and earlier, is to use
one extra level of indirection:
def __getFoo(self): return self.getFoo()
def getFoo(self): ...
foo = property(__getFoo)
so the name lookup for 'getFoo' on self happens when you access s.foo
(for s being an instance of this here-sketched class) and overriding
works just as expected. This can be seen as the simplest possible use
case for the "Template Method" Design Pattern, btw;-)


Alex
 
S

Steven Bethard

Alex said:
[snip]
the solution, in Python 2.4 and earlier, is to use
one extra level of indirection:
def __getFoo(self): return self.getFoo()
def getFoo(self): ...
foo = property(__getFoo)
so the name lookup for 'getFoo' on self happens when you access s.foo
(for s being an instance of this here-sketched class) and overriding
works just as expected.

Another solution (for those of you scoring at home) would be to use a
property-like descriptor that delays the name lookup until the time of
the method call, e.g.

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/408713

STeVe
 
B

beza1e1

let me try.

1) ''.join(lots_of_pieces)

2) This doesn't even work, if something is removed, the list is too
short. So:
[x for x in somelist if not isbad(x)]
well, list comprehension is Python 2.4 and 2.3 is the standard in many
OSes, so it is possibly not the most portable solution
I had to look up the syntax, because i never use it in my code, yet.

3+4) I never used property - had to look it up. So i learned something
:)
 
S

Steve Holden

beza1e1 said:
let me try.

1) ''.join(lots_of_pieces)

2) This doesn't even work, if something is removed, the list is too
short. So:
[x for x in somelist if not isbad(x)]
well, list comprehension is Python 2.4 and 2.3 is the standard in many
OSes, so it is possibly not the most portable solution
I had to look up the syntax, because i never use it in my code, yet.

Python 2.2.1 (#1, Aug 25 2004, 16:56:05)
[GCC 2.95.4 20011002 (Debian prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> [a.upper() for a in ['two', 'point', 'two']] ['TWO', 'POINT', 'TWO']
>>>
3+4) I never used property - had to look it up. So i learned something
:)
regards
Steve
 
P

Peter Hansen

beza1e1 said:
well, list comprehension is Python 2.4 and 2.3 is the standard in many
OSes, so it is possibly not the most portable solution

You're probably remembering "generator expressions", which were added in
Python 2.4 and aren't available in earlier versions. They fit in a
similar place in one's mind, anyway....

-Peter
 
A

Alex Martelli

beza1e1 said:
let me try.

1) ''.join(lots_of_pieces)
Yep.

2) This doesn't even work, if something is removed, the list is too
short. So:
[x for x in somelist if not isbad(x)]
well, list comprehension is Python 2.4 and 2.3 is the standard in many
OSes, so it is possibly not the most portable solution

No, LC goes back a long way -- I think it was in 2.0 already, 2.1 for
sure. If you have to support (say) Python 1.5.2, the simplest (not
fastest) solution is to loop on a COPY of the list, rather than the very
list you're also modifying.
I had to look up the syntax, because i never use it in my code, yet.

3+4) I never used property - had to look it up. So i learned something
:)

Good!-)


Alex
 
T

Tim Roberts

PyPK said:
What possible tricky areas/questions could be asked in Python based
Technical Interviews?

What's the point of asking "tricky" questions? Aren't you really more
interested in what applications they have worked on and whether they were
successful?

I don't know. I'm not sure I need a job with a company that insists on
playing "Programming Jeopardy" during the interview.
 
P

Peter Hansen

Tim said:
What's the point of asking "tricky" questions? Aren't you really more
interested in what applications they have worked on and whether they were
successful?

I don't know. I'm not sure I need a job with a company that insists on
playing "Programming Jeopardy" during the interview.

That's okay. Those companies don't need you either. ;-)

Seriously though, the point of asking such questions is that with
minimal effort they _can_ (not "definitely will") quickly qualify a
candidate's level of expertise in a language. Novices, and those who
while they might have programmed in a language for several years still
don't really understand it deeply enough to be considered entirely safe
on their own, will generally trip up on all or most such questions
(where "trip up" means anything from giving wrong answers to giving you
the "deer in the headlights" look). _Anyone_ could trip up on one or
two of them, especially given the pressure of an interview situation.
(And even seeing an expert trip up under pressure tells you something
useful about the candidate.)

In short, a true senior programmer will provide good correct answers to
most such questions, while those less senior generally will not.

Asking such questions in isolation, without also delving deeply into
other background such as what applications you've worked on, is just as
dangerous as asking _only_ about such applications. I've made the
mistake of hiring people who had lengthy involvement -- apparently at a
senior level -- in significant projects, only to discover that they
clearly didn't understand some basic concepts of the languages
supposedly used. My conclusion was that they were in that class of
people who manage to interview well yet contribute little, but have
lucked out repeatedly by working for companies who were incompetent at
terminating for cause (and there are _many_ such companies). (We didn't
make the same mistake and fired them reasonably quickly.)

-Peter
 
F

Fredrik Lundh

Alex said:
No, LC goes back a long way -- I think it was in 2.0 already, 2.1 for
sure.

$ python1.5 -c "print [x for x in 'abc']"
File "<string>", line 1
print [x for x in 'abc']
^
SyntaxError: invalid syntax
$ python2.0 -c "print [x for x in 'abc']"
['a', 'b', 'c']

I was a bit surprised to find that 2.0 had variables, though:

$ python2.0 -c "[x for x in y]"
Traceback (most recent call last):
File "<string>", line 1, in ?
NameError: There is no variable named 'y'
$ python2.1 -c "[x for x in y]"
Traceback (most recent call last):
File "<string>", line 1, in ?
NameError: name 'y' is not defined

;-)

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,269
Messages
2,571,338
Members
48,026
Latest member
DannieKeeg

Latest Threads

Top