PyPK wrote:[color=blue]
> What possible tricky areas/questions could be asked in Python based
> Technical Interviews?[/color]
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.
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).
PyPK <superprad@gmai l.com> wrote:
[color=blue]
> What possible tricky areas/questions could be asked in Python based
> Technical Interviews?[/color]
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 "disqualify ing" -- it
would just mean I'd rate the candidate 4 out of five, instead of 4.5 or
more, for Python coding competence).
On 10/24/05, Alex Martelli <aleaxit@yahoo. com> wrote:[color=blue]
> 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[/color]
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 Durdin <adurdin@gmail. com> wrote:
[color=blue]
> On 10/24/05, Alex Martelli <aleaxit@yahoo. com> wrote:[color=green]
> > 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[/color]
>
> 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.[/color]
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 Martelli wrote:
[color=blue]
> 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.[/color]
[snip]
[color=blue]
> 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[/color]
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:
[color=blue]
> 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): ....[/color]
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?
Steven D'Aprano wrote:[color=blue]
> Alex Martelli wrote:[/color]
[color=blue]
> 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:
>[color=green]
>> class Base(object)
>> def getFoo(self): ...
>> def setFoo(self): ...
>> foo = property(getFoo , setFoo)
>>
>> class Derived(Base):
>> def getFoo(self): ....[/color]
>
>
> 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?[/color]
Derived.getFoo( ) will not override the use of Base.getFoo() to access the attribute foo.
Steven D'Aprano wrote:
[color=blue]
> 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:[/color]
[color=blue][color=green]
>> class Base(object)
>> def getFoo(self): ...
>> def setFoo(self): ...
>> foo = property(getFoo , setFoo)
>>
>> class Derived(Base):
>> def getFoo(self): ....[/color][/color]
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 getFooDispatche r(self): self.getFoo() # use normal lookup
def setFooDispatche r(self, ...): self.setFoo(... ) # use normal lookup
foo = property(getFoo Dispatcher, setFooDispatche r)
Steven D'Aprano <steve@REMOVEME cyber.com.au> wrote:
...[color=blue]
> my hard-won ignorance, and admit that I don't see the
> problem with the property examples:
>[color=green]
> > class Sic:
> > def getFoo(self): ...
> > def setFoo(self): ...
> > foo = property(getFoo , setFoo)[/color][/color]
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).
[color=blue][color=green]
> > to
> > class Base(object)
> > def getFoo(self): ...
> > def setFoo(self): ...
> > foo = property(getFoo , setFoo)
> >
> > class Derived(Base):
> > def getFoo(self): ....[/color]
>
> Unless the answer is "Why are you using setters and
> getters anyway? This isn't Java you know."[/color]
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(__getF oo)
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 Martelli wrote:[color=blue]
>[color=green][color=darkred]
>>> class Base(object)
>>> def getFoo(self): ...
>>> def setFoo(self): ...
>>> foo = property(getFoo , setFoo)
>>>
>>> class Derived(Base):
>>> def getFoo(self): ....[/color]
>>[/color][/color]
[snip][color=blue]
> 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(__getF oo)
> 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.[/color]
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.
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
:)
beza1e1 wrote:[color=blue]
> 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.[/color]
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.[color=blue][color=green][color=darkred]
>>> [a.upper() for a in ['two', 'point', 'two']][/color][/color][/color]
['TWO', 'POINT', 'TWO'][color=blue][color=green][color=darkred]
>>>[/color][/color][/color]
[color=blue]
>
> 3+4) I never used property - had to look it up. So i learned something
> :)
>[/color]
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/
Comment