By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,818 Members | 1,282 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,818 IT Pros & Developers. It's quick & easy.

sufficiently pythonic code for testing type of function

P: n/a
I wrote this for someone else to take an object and list of types,
then check if obj is one of those types, raising an error otherwise.

Is it enough to rely on side effects or absence thereof, or should I
put return True in here somewhere?

def test_obj_type(obj, types):
for type in types:
if isinstance(obj, type):
break
else:
raise ValueError, 'object is not in %s' % types

-- Theerasak
Oct 11 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Theerasak Photha wrote:
I wrote this for someone else to take an object and list of types,
then check if obj is one of those types, raising an error otherwise.

Is it enough to rely on side effects or absence thereof, or should I
put return True in here somewhere?

def test_obj_type(obj, types):
for type in types:
if isinstance(obj, type):
break
else:
raise ValueError, 'object is not in %s' % types
Hello Theerasak,

To answer your question: Either (a) return True if OK, False if not OK
or (b) make it like an assertion: raise an exception if not OK, do
nothing if OK. Returning True from the above function would be a rather
strange hybrid.

However:

1. if isinstance(obj, types[1] is true, but isinstance(obj, types[0])
is false, this would appear to raise ValueError. Is the indentation of
the else and raise what you intended?

2. In any case, since Python 2.2, no loop is necessary:

def test_obj_type(obj, types):
if not isinstance(obj, types):
raise ValueError, 'object is not in %s' % (types, )

If you don't want the assertion style, your "someone else" can call
isinstance directly.

3. And please notice the change in the raise line; if types is a tuple
of two or more items, the % operator treats it specially. As coded, you
would get this exception:
"TypeError: not all arguments converted during string formatting"

HTH,
John

Oct 11 '06 #2

P: n/a
Theerasak Photha wrote:
I wrote this for someone else to take an object and list of types,
then check if obj is one of those types,
This is already what isinstance(obj, tuple_of_types) does.
raising an error otherwise.

Is it enough to rely on side effects or absence thereof, or should I
put return True in here somewhere?
What for ?
def test_obj_type(obj, types):
for type in types:
if isinstance(obj, type):
break
else:
raise ValueError, 'object is not in %s' % types


def checkinstanceof(obj, types):
if not isinstance(obj, types):
raise ValueError('object is not an instance of %s' % str(types))
Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?
-- Theerasak

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 11 '06 #3

P: n/a
On 10/11/06, Bruno Desthuilliers <on***@xiludom.growrote:
Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?
Perhaps:

try:
for attribute in ['foo', 'bar', '__baz__']:
getattr(mystery_object, '__%s__' % attribute)
except AttributeError:
# Do sumthin bout it

Is it wrong to 're-raise' an exception with application-specific
details within an except clause?

-- Theerasak
Oct 11 '06 #4

P: n/a
Theerasak Photha wrote:
>Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?

Perhaps:

try:
for attribute in ['foo', 'bar', '__baz__']:
getattr(mystery_object, '__%s__' % attribute)
except AttributeError:
# Do sumthin bout it

Is it wrong to 're-raise' an exception with application-specific
details within an except clause?
nope, as long as the new exception is provides more accurate information
about what actually happened. something like

try:
do something
except ValueError:
raise RuntimeError("the frobnitz failed to catch the kitten")

can be a lot better than a 30-level traceback that ends with a line
looking something like

fnut.index(gah)

on the other hand, things like this are all too common:

try:
do something
except:
raise Exception("something happened")

also, checking for __method__ is, in general, not the right way to check
if an object implements a given interface. some types use C-level slots
or alternative hooks to provide functionality, and such things are not
always visible from the outside (Python knows how to use them, though).

so if you can, try doing the operation instead, and catch error (if you
really need to check first, use an idempotent operation, if available).

</F>

Oct 11 '06 #5

P: n/a
On 10/11/06, Fredrik Lundh <fr*****@pythonware.comwrote:
can be a lot better than a 30-level traceback that ends with a line
looking something like

fnut.index(gah)
Despite long experience with Perl, I am not a big follower of the
"goose_level: blah" method of error reporting...
also, checking for __method__ is, in general, not the right way to check
if an object implements a given interface.
I had a vague feeling it might not be a Right Thing(tm).
<flame-proof-underwear>I kind of miss
responds_to?</flame-proof-underwear>
so if you can, try doing the operation instead, and catch error (if you
really need to check first, use an idempotent operation, if available).
I'll do that as soon as my green noggin figures out what 'idempotent' means.

Serves me right for being a liberal arts weenie:
http://www.c2.com/cgi/wiki?ThaiLanguage

-- Theerasak
Oct 11 '06 #6

P: n/a
Theerasak Photha wrote:
I'll do that as soon as my green noggin figures out what 'idempotent' means.
"Acting as if used only once, even if used multiple times", to quote
the first explanation I saw on the google result page.

and from the irony department, googling for "indempotent" provides an
even clearer explanation: "Refers to an operation that produces the same
results no matter how many times it is performed."

</F>

Oct 11 '06 #7

P: n/a
Theerasak Photha wrote:
On 10/11/06, Fredrik Lundh <fr*****@pythonware.comwrote:
>can be a lot better than a 30-level traceback that ends with a line
looking something like

fnut.index(gah)

Despite long experience with Perl, I am not a big follower of the
"goose_level: blah" method of error reporting...
>also, checking for __method__ is, in general, not the right way to check
if an object implements a given interface.

I had a vague feeling it might not be a Right Thing(tm).
<flame-proof-underwear>I kind of miss
responds_to?</flame-proof-underwear>
getattr(obj, name[,default]) is your friend. Remember that methods are
just callable attributes.
>so if you can, try doing the operation instead, and catch error (if you
really need to check first, use an idempotent operation, if available).

I'll do that as soon as my green noggin figures out what 'idempotent'
means.
idempotent -no side effects.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 11 '06 #8

P: n/a
On 2006-10-11, Bruno Desthuilliers <on***@xiludom.growrote:
>
Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?
one possible answer: Use ZopeInterfaces
(and ask objects 'do you implement interface X' rather than 'are you type Y')

Not sure what options you have when dealing with builtin data types however.
Albert
Oct 11 '06 #9

P: n/a
A.T.Hofkamp wrote:
On 2006-10-11, Bruno Desthuilliers <on***@xiludom.growrote:
>Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?

one possible answer: Use ZopeInterfaces
(and ask objects 'do you implement interface X' rather than 'are you type Y')

Not sure what options you have when dealing with builtin data types however.
This was mostly a rethorical question...
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 11 '06 #10

P: n/a

Theerasak Photha a écrit :
On 10/11/06, Bruno Desthuilliers <on***@xiludom.growrote:
Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?

Perhaps:

try:
for attribute in ['foo', 'bar', '__baz__']:
getattr(mystery_object, '__%s__' % attribute)
except AttributeError:
# Do sumthin bout it
Isn't this a case of useless overcomplexification ? Since you end up
raising an exception, why not just assume the object is ok and let
Python raise the exception for you if it is not ? From the client code
POV, it doesn't make much difference !-)

Is it wrong to 're-raise' an exception with application-specific
details within an except clause?
Nope - as long as you provide more details (or more helpful details)
*and* do not loose/mask/whatever useful infos from the original
exception.

Oct 11 '06 #11

P: n/a
On 2006-10-11, Bruno Desthuilliers <on***@xiludom.growrote:
A.T.Hofkamp wrote:
>On 2006-10-11, Bruno Desthuilliers <on***@xiludom.growrote:
>>Now the real question : what if the object is not an instance of any of
the types, but still support the expected interface ?

one possible answer: Use ZopeInterfaces
(and ask objects 'do you implement interface X' rather than 'are you type Y')

Not sure what options you have when dealing with builtin data types however.

This was mostly a rethorical question...
And even for rethorical questions, Python already provides a solution.. :-)

Albert
Oct 12 '06 #12

P: n/a
On 10/11/06, Bruno Desthuilliers <on***@xiludom.growrote:
Theerasak Photha wrote:
On 10/11/06, Fredrik Lundh <fr*****@pythonware.comwrote:
can be a lot better than a 30-level traceback that ends with a line
looking something like

fnut.index(gah)
Despite long experience with Perl, I am not a big follower of the
"goose_level: blah" method of error reporting...
also, checking for __method__ is, in general, not the right way to check
if an object implements a given interface.
I had a vague feeling it might not be a Right Thing(tm).
<flame-proof-underwear>I kind of miss
responds_to?</flame-proof-underwear>

getattr(obj, name[,default]) is your friend. Remember that methods are
just callable attributes.
I am familiar with getattr from the Introspection material in Dive
into Python of course.

Earlier in the thread we decided that using getattr is the Wrong
Way(tm) to decide whether an object has such and such operation
(respond_to?) because implementation details can hide this.

So I learned the best thing to do is Suck It And See (an electrical
joke, not a penis joke, BION) aka EAFP.

I just found out Ruby isn't much better in this regard:

class Foo
def self.method_missing(meth, *args)
puts meth
end
end

Foo.bar()
puts Foo.respond_to?(:bar)

===>
bar
false

WTF?

-- Theerasak
Oct 13 '06 #13

P: n/a
Bruno Desthuilliers wrote:
... idempotent -no side effects.
Nope. idempotent: f(f(x)) = f(x)
That is, after doing it once, repeating it won't hurt.

--Scott David Daniels
sc***********@acm.org
Oct 13 '06 #14

P: n/a
Scott David Daniels wrote:
Nope. idempotent: f(f(x)) = f(x)
That is, after doing it once, repeating it won't hurt.
http://en.wikipedia.org/wiki/Idempot...ter_science%29

</F>

Oct 13 '06 #15

P: n/a
Fredrik Lundh wrote:
Scott David Daniels wrote:
>Nope. idempotent: f(f(x)) = f(x)
That is, after doing it once, repeating it won't hurt.

http://en.wikipedia.org/wiki/Idempot...ter_science%29

</F>
Thank you (Scott and Fredrik) for the correction.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 16 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.