470,826 Members | 1,788 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,826 developers. It's quick & easy.

Object type check

Hi to all,

in statically-types languages, let's say C# for example, we use
polymorphism through interfaces. So we define an interface I with
method M and then a class C that implements I interface and write code
for the M method.
So, if we have a function that takes a parameter of type I, we know
before-hand that it will have an M method to call.

But in dynamic languages this is not the case and we can pass whatever
we want to that function. Assuming that someone writes a library in
Python that other programmers will use, what is the correct way to
check inside that function if the parameter passed is of the correct
type, maybe "isinstance" BIF ?

Thanks in advance!

Feb 7 '07 #1
16 2509
The answer is to do nothing at all. Use the interfaces of the objects
that you expect. Treat them like numbers if you expect them to be, or
stirngs, or iterables. Call methods and access attributes you expect
to be there. If the caller passes sometihng bad, and something doesn't
work, they'll find out about it and consult your documentation to see
what they did wrong. Dont restrict them to particular types. You would
not restrict them to a particular class in C#. Instead, you define the
interfaces simply by how you use the objects. This is called duck
typing (http://en.wikipedia.org/wiki/Duck_typing) which states "If it
walks like a duck and it quacks like a duck, it must be a duck." In
the end, isn't that what matters to you? Not the type or defined
interfaces of an object, but that it does what you expect.

On 7 Feb 2007 08:17:55 -0800, king kikapu <ab********@panafonet.grwrote:
Hi to all,

in statically-types languages, let's say C# for example, we use
polymorphism through interfaces. So we define an interface I with
method M and then a class C that implements I interface and write code
for the M method.
So, if we have a function that takes a parameter of type I, we know
before-hand that it will have an M method to call.

But in dynamic languages this is not the case and we can pass whatever
we want to that function. Assuming that someone writes a library in
Python that other programmers will use, what is the correct way to
check inside that function if the parameter passed is of the correct
type, maybe "isinstance" BIF ?

Thanks in advance!

--
http://mail.python.org/mailman/listinfo/python-list

--
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://ironfroggy-code.blogspot.com/
Feb 7 '07 #2
On Feb 7, 5:17 pm, "king kikapu" <aboudou...@panafonet.grwrote:
Hi to all,

in statically-types languages, let's say C# for example, we use
polymorphism through interfaces. So we define an interface I with
method M and then a class C that implements I interface and write code
for the M method.
So, if we have a function that takes a parameter of type I, we know
before-hand that it will have an M method to call.

But in dynamic languages this is not the case and we can pass whatever
we want to that function. Assuming that someone writes a library in
Python that other programmers will use, what is the correct way to
check inside that function if the parameter passed is of the correct
type, maybe "isinstance" BIF ?
Usually, you don't check anything at all. However, in some cases, it
may make
sense to check that you passed the right object.
For instance if you have the container

class Example(object):
def __init__(self, innerobj):
self.innerobj = innerobj
def amethod(self):
self.innerobj.amethod()

ex = Example(None)

you will get an error only when calling ex.amethod(). If you are going
to call
ex.amethod() one hour after instantiation, you will get the error too
late.
So, it makes sense to put a check in the __init__ method, something
like

assert hasattr(self.innerobj, 'amethod')

in order to get an error message as soon as possible. Notice that
checking for the existance
of the needed method is better than using isinstance, since it gives
you much more
freedom for innerobj. Do not require more than you need.
HTH,

Michele Simionato

Feb 7 '07 #3
Dont restrict them to particular types. You would
not restrict them to a particular class in C#. Instead, you define the
interfaces simply by how you use the objects.
Of cource i restrict them to particular types! In C# you cannot pass
something bad
this way because the compiler will just catch it!

I see what you mean by "duck typing". So you suggest the "do nothing
at all" direction,
better document my code so other can see what is expected, right ?

Feb 7 '07 #4
On 7 Feb 2007 08:59:12 -0800, king kikapu <ab********@panafonet.grwrote:
Dont restrict them to particular types. You would
not restrict them to a particular class in C#. Instead, you define the
interfaces simply by how you use the objects.

Of cource i restrict them to particular types! In C# you cannot pass
something bad
this way because the compiler will just catch it!
No, you restrict the interfaces, in your example, not the classes. It
is the same in python, but the interfaces are implicitly defined by
how you use the objects.
I see what you mean by "duck typing". So you suggest the "do nothing
at all" direction,
better document my code so other can see what is expected, right ?
Yes. Also, remember that this means if you write code to expect a
dictionary, any mapping type that supports the operations and methods
you use will work transparently, allowing your code to be much more
flexible.

--
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://ironfroggy-code.blogspot.com/
Feb 7 '07 #5
Of cource i restrict them to particular types! In C# you cannot pass
something bad
this way because the compiler will just catch it!
And you cant pass something 'good' that immitates another object
interface (a file-like object for example)
I see what you mean by "duck typing". So you suggest the "do nothing
at all" direction,
better document my code so other can see what is expected, right ?
I would add UnitTests to it.
--
EduardoOPadoan (eopadoan->altavix::com)
Feb 7 '07 #6
king kikapu a écrit :
Hi to all,

in statically-types languages, let's say C# for example, we use
polymorphism through interfaces. So we define an interface I with
method M and then a class C that implements I interface and write code
for the M method.
So, if we have a function that takes a parameter of type I, we know
before-hand that it will have an M method to call.

But in dynamic languages this is not the case and we can pass whatever
we want to that function.
Yes. And this is a Good Thing (tm).
Assuming that someone writes a library in
Python that other programmers will use, what is the correct way to
check inside that function if the parameter passed is of the correct
type, maybe "isinstance" BIF ?
The correct way in Python is to *not* check. Just document what kind of
interface you expect, and it's ok. If the people using your code are stupid
and lazy enough to not read the doc, then you can't help .

Feb 7 '07 #7
king kikapu a crit :
>>Dont restrict them to particular types. You would
not restrict them to a particular class in C#. Instead, you define the
interfaces simply by how you use the objects.


Of cource i restrict them to particular types! In C# you cannot pass
something bad
this way because the compiler will just catch it!
This won't prevent some stupid to implement the interface with a totally
different semantic (what about some getter wiping out your hard drive ?).

FWIW, in Python, you can't pass something bad because it will raise an
exception. Well, to be true, there's *one* gotcha : passing a string
where a list or tuple is expected may in some occasions yield strange
results (strings being sequences too).
I see what you mean by "duck typing". So you suggest the "do nothing
at all" direction,
better document my code so other can see what is expected, right ?
Exactly.
Feb 7 '07 #8
at first, thanks you all for your help!

So, i will follow your advice.In a moment though, i thought that "ok,
do not check anything of the parameter's type but do a try/catch at
the calls inside the function"

But this way, i would rather defeat the purpose because i have to try/
catch in *every* call inside the func.
So, i suppose that i wouldn't want to do that and just try to make the
call in whatever they passed me in.

Strange world the dynamic one....

Feb 7 '07 #9
king kikapu a écrit :
at first, thanks you all for your help!

So, i will follow your advice.In a moment though, i thought that "ok,
do not check anything of the parameter's type but do a try/catch at
the calls inside the function"
And so what ? Once an exception got caught, what are you going to do ?
Raise another exception ? Re-raise the same exception ? In both cases, you
usually don't gain much - and sometimes loose (time, simplicity,
readability, and
a usefull traceback).

Unless you know how to handle it, it's usually better to let the exception
propagate. Usually, the person coding the *application* (ie: the coder using
your lib) will wrap the whole thing into a catch-all exception handler
at the higher level,
so he can log the full traceback, display a nice error to the end user,
and crash gracefully.
As a library programmer, you should not care about this.
But this way, i would rather defeat the purpose because i have to try/
catch in *every* call inside the func.
So, i suppose that i wouldn't want to do that and just try to make the
call in whatever they passed me in.
You're starting to see the light, my friend !-)
Strange world the dynamic one....
If that's too dynamic for you, then run for your life - this is just the
visible
part of the iceberg.
Feb 7 '07 #10
And so what ? Once an exception got caught, what are you going to do ?

You have absolutely right, that's the reason i rejected this.
You're starting to see the light, my friend !-)
Strange world the dynamic one....

If that's too dynamic for you, then run for your life

Hehe...you know, it is a little bit strange if you are used to Delphi,
C# or any other statically-typed language and suddenly you starting
programming in a dynamic one, really strange! :)
All of the efforts all these years to declare everything correct, to
fight with the compiler (and to always have him win...), to ...[put
whatever here] and now Python...What can i say!...

Thanks for the help!

Feb 7 '07 #11
king kikapu a écrit :
>>And so what ? Once an exception got caught, what are you going to do ?


You have absolutely right, that's the reason i rejected this.
hear hear !-)

( snip)
All of the efforts all these years to declare everything correct, to
fight with the compiler (and to always have him win...), to ...[put
whatever here] and now Python...What can i say!...
http://www.lesher.ws/choose_python.pdf

Feb 7 '07 #12
On Wed, 07 Feb 2007 08:59:12 -0800, king kikapu wrote:
I see what you mean by "duck typing". So you suggest the "do nothing
at all" direction,
better document my code so other can see what is expected, right ?
Generally speaking, yes, but not always.

The usual Python model is "better to ask forgiveness than permission". For
example, these two snippets of code do (more or less) the same thing, but
the second is more in the Pythonic style:
# Look Before You Leap
if isinstance(x, SomeClass):
x.somemethod()
else:
do_something_else()

# Better To Ask For Forgiveness Than Permission
try:
x.somemethod()
except AttributeError: # no such method exists
do_something_else()
Setting up a try...except block is cheap in Python, so it costs very
little to try calling the method, then take a different action only if it
is one of the rare failures. (However, catching the exception is
expensive, so if you have lots of failures, you might want to rethink your
strategy.)

But sometimes this isn't what you want. Here's a counter example:

def modify(list_of_x):
for x in list_of_x:
x.change_in_place()

Note that there's no "do_something_else" to do if an item doesn't have
the correct method. That's bad data, and no recovery is possible, so
you just let the exception propagate. But there's a problem: if the
calling code catches the exception, as it may, you leave the list_of_x
in an intermediate state where some of the items have been changed and
some haven't.

The solution is a form of Look Before You Leap that doesn't break
duck-typing:

def modify(list_of_x):
for x in list_of_x:
try:
x.change_in_place # don't call the method, just check it exists
# we can check as many or as few methods as we need, e.g.:
x.__getitem__ # check that x is indexable
except AttributeError:
raise ValueError("list contains an invalid item")
# if we get here, we know it is safe to proceed
for x in list_of_x:
x.change_in_place()

Now each item doesn't have to be an instance of SomeClass, but merely
needs to have the right signature.
--
Steven D'Aprano

Feb 8 '07 #13
def modify(list_of_x):
for x in list_of_x:
try:
x.change_in_place # don't call the method, just check it exists
XXmmmm...what exactly is going on here ? I mean, what is actually
happens if you omit the parenethesis as you just did ? I understand
that it does not call the method, but what is really doing ??

Feb 8 '07 #14
On Feb 8, 12:00 pm, "king kikapu" <aboudou...@panafonet.grwrote:
def modify(list_of_x):
for x in list_of_x:
try:
x.change_in_place # don't call the method, just check it exists

XXmmmm...what exactly is going on here ? I mean, what is actually
happens if you omit the parenethesis as you just did ? I understand
that it does not call the method, but what is really doing ??
See http://users.rcn.com/python/download/Descriptor.htm for more than
you ever wanted
to know about attribute access in Python.

Michele Simionato

Feb 8 '07 #15

/ Michele Simionato :
See http://users.rcn.com/python/download/Descriptor.htm for more than
you ever wanted
to know about attribute access in Python.

Michele Simionato
Great stuff Michele, thanks!

Feb 8 '07 #16
On Thu, 08 Feb 2007 03:00:39 -0800, king kikapu wrote:
>def modify(list_of_x):
for x in list_of_x:
try:
x.change_in_place # don't call the method, just check it exists

XXmmmm...what exactly is going on here ? I mean, what is actually
happens if you omit the parenethesis as you just did ? I understand
that it does not call the method, but what is really doing ??
The same as for any attribute: x.name gives the object referred to by the
attribute name, and x.name() calls that object.

He's a simple example:
>>def foo():
.... return "foo"
....
>>type(foo) # the name alone
<type 'function'>
>>type(foo()) # call the function
<type 'str'>
--
Steven.

Feb 9 '07 #17

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

39 posts views Thread by eruanion | last post: by
13 posts views Thread by Fredrik Strandberg | last post: by
6 posts views Thread by tommaso.gastaldi | last post: by
21 posts views Thread by phpCodeHead | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.