Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Checking if a variable is a dictionary

18 views
Skip to first unread message

Guillermo

unread,
Mar 6, 2008, 7:10:47 AM3/6/08
to

Hello,

This is my first post here. I'm getting my feet wet with Python and I
need to know how can I check whether a variable is of type dictionary.

Something like this:

if isdict(a) then print "a is a dictionary"

Regards,

Guillermo

Sam

unread,
Mar 6, 2008, 7:15:17 AM3/6/08
to
Hello

if type(a) is dict:
print "a is a dictionnary!"

++

Sam


Gabriel Genellina

unread,
Mar 6, 2008, 7:35:38 AM3/6/08
to pytho...@python.org
En Thu, 06 Mar 2008 10:10:47 -0200, Guillermo
<guillerm...@googlemail.com> escribi�:

> This is my first post here. I'm getting my feet wet with Python and I
> need to know how can I check whether a variable is of type dictionary.
>
> Something like this:
>
> if isdict(a) then print "a is a dictionary"

if isinstance(a, dict): ...

But note that it's more common in Python to try to use it in the intended
way, and catch the possible errors.
Look for "duck typing" in this group, and the difference between "easier
to ask forgiveness
than permission" and "look before you leap".

--
Gabriel Genellina

Bruno Desthuilliers

unread,
Mar 6, 2008, 7:40:17 AM3/6/08
to
Guillermo a écrit :

> Hello,
>
> This is my first post here. I'm getting my feet wet with Python and I
> need to know how can I check whether a variable is of type dictionary.

What makes you say you "need" to know this ? Except for a couple corner
cases, you usually don't need to care about this. If you told us more
about the actual problem (instead of asking about what you think is the
solution), we might be of more help...

> Something like this:
>
> if isdict(a) then print "a is a dictionary"

Should this work for subclasses of dicts ? Should this work for
non-subclasses of dict implementing the dict protocol ?

Bruno Desthuilliers

unread,
Mar 6, 2008, 7:41:20 AM3/6/08
to
Sam a écrit :

> Hello
>
> if type(a) is dict:
> print "a is a dictionnary!"


class MyDict(dict):
pass

a = MyDict()

type(a) is dict
=> False

Guillermo

unread,
Mar 6, 2008, 8:06:50 AM3/6/08
to

Wow, I think I'm gonna like this forum. Thank you all for the prompt
answers!

>What makes you say you "need" to know this ? Except for a couple corner
>cases, you usually don't need to care about this. If you told us more
>about the actual problem (instead of asking about what you think is the
>solution), we might be of more help...

Good point.

I want to iterate recursively a dictionary whose elements might be
strings or nested tuples or dictionaries and then convert values to a
tagged format according to some rules.

d = {'a':"i'm a", 'b':(1,2,3),'c':{'a':"i'm a",'x':"something",'y':
('a','b','c')}}

I'm just designing the algorithm, but I think Python dictionaries can
hold any kind of sequence?

Regards,

Guillermo

Message has been deleted

Bjoern Schliessmann

unread,
Mar 6, 2008, 9:24:29 AM3/6/08
to
Guillermo wrote:

> I'm just designing the algorithm, but I think Python dictionaries
> can hold any kind of sequence?

(Watch out, dicts are no sequence types.)

I recommend relying duck typing as long as it's feasible. I. e. if
it can be subscripted like a dict, it is a dict. If this makes
problems, use the type({}) approach.

Regards,


Björn

--
BOFH excuse #56:

Electricians made popcorn in the power supply

Martin Marcher

unread,
Mar 6, 2008, 9:26:27 AM3/6/08
to pytho...@python.org
On Thu, Mar 6, 2008 at 2:06 PM, Guillermo
<guillerm...@googlemail.com> wrote:
> >What makes you say you "need" to know this ? Except for a couple corner
> >cases, you usually don't need to care about this. If you told us more
> >about the actual problem (instead of asking about what you think is the
> >solution), we might be of more help...
>
> I want to iterate recursively a dictionary whose elements might be
> strings or nested tuples or dictionaries and then convert values to a
> tagged format according to some rules.

just do so, if it's not a dict you can always catch the exception,
then handle tuples (or the exception), then strings which should work
always (of course also error handling here according to your needs)

> I'm just designing the algorithm, but I think Python dictionaries can
> hold any kind of sequence?

python dicts can hold any kind of object (as a value). What you can't
do is have a list as the key, but that is easily circumvented by using
a tuple (or any other immutable type).


hth
martin

--
http://tumblr.marcher.name
https://twitter.com/MartinMarcher
http://www.xing.com/profile/Martin_Marcher
http://www.linkedin.com/in/martinmarcher

You are not free to read this message,
by doing so, you have violated my licence
and are required to urinate publicly. Thank you.

Bruno Desthuilliers

unread,
Mar 6, 2008, 9:47:39 AM3/6/08
to
Guillermo a écrit :

> Wow, I think I'm gonna like this forum. Thank you all for the prompt
> answers!

Welcome onboard !-)

>> What makes you say you "need" to know this ? Except for a couple corner
>> cases, you usually don't need to care about this. If you told us more
>> about the actual problem (instead of asking about what you think is the
>> solution), we might be of more help...
>
> Good point.
>
> I want to iterate recursively a dictionary whose elements might be
> strings or nested tuples or dictionaries and then convert values to a
> tagged format according to some rules.

If you're absolutely definitively 101% sure that you'll never have
anything else in your dict - IOW : this dict is an internal part of your
module, produced by the module and consumed by the module -, then it
*might* be one of the corner cases where testing type (either directly
or - preferably - via isinstance) is the right thing to do.

> d = {'a':"i'm a", 'b':(1,2,3),'c':{'a':"i'm a",'x':"something",'y':
> ('a','b','c')}}
>
> I'm just designing the algorithm, but I think Python dictionaries can
> hold any kind of sequence?

Any Python object (which include classes, modules, functions etc) can be
used as value.

Bruno Desthuilliers

unread,
Mar 6, 2008, 9:52:41 AM3/6/08
to
Jeffrey Seifried a écrit :
(snip)
> if type(a)==type({}):
> print 'a is a dictionary'

This instanciates a dict, call type() on it, and discard the dict -
which is useless since the dict type is a builtin. Also, when you want
to test identity, use an identity test.

if type(a) is dict:
print "blah blah blah"

Neil Cerutti

unread,
Mar 6, 2008, 10:25:07 AM3/6/08
to pytho...@python.org
On Thu, Mar 6, 2008 at 8:06 AM, Guillermo
<guillerm...@googlemail.com> wrote:
> I want to iterate recursively a dictionary whose elements might be
> strings or nested tuples or dictionaries and then convert values to a
> tagged format according to some rules.
>
> d = {'a':"i'm a", 'b':(1,2,3),'c':{'a':"i'm a",'x':"something",'y':
> ('a','b','c')}}

This could be solved with dynamic polymorphism instead of
introspection, which might simplify things depending on how your
dictionary is constructed.

class Value(object):
def to_tagged_format(self):
raise NotImplementedError

class StringValue(Value):
def to_tagged_format(self):
...

class Tuplevalue(Value):
def to_tagged_format(self):
...
class DictValue(Value):
def to_tagged_format(self):
...


for k, v in d.iteritems():
d[k] = v.to_tagged_format()

You can also get the dynamic polymorphism without invoking inheritance
by specifying a protocol that the values in your dict must implement,
instead. Protocols are plentiful in Python, perhaps more popular than
type hierarchies.

--
Neil Cerutti <mr.cerut...@gmail.com>

Guillermo

unread,
Mar 6, 2008, 12:17:31 PM3/6/08
to
> You can also get the dynamic polymorphism without invoking inheritance
> by specifying a protocol that the values in your dict must implement,
> instead. Protocols are plentiful in Python, perhaps more popular than
> type hierarchies.

I'm used to languages with stricter rules than Python. I've read a bit
about Python protocols, but where could I get some more info on
implementation details? Sounds very interesting.

Regards,

Guillermo

Neil Cerutti

unread,
Mar 6, 2008, 1:17:28 PM3/6/08
to pytho...@python.org

A protocol is just an interface that an object agrees to implement. In
your case, you would state that every object stored in your special
dict must implement the to_tagged_value method with certain agreeable
semantics.

Python implements sequence types, mapping types, iterators, file
streams, and other things with protocols.

For example, iterators must support the "next" and and "__iter__" methods.

Using a protocol instead instead of a type hierarchy requires less
boring boilerplate, and I suppose in Python will usuallly be
preferable except when you want to inherit implementation as well as
interface. In that case, inheritance often saves boilerplate cide
rather than increases it.

It's also misnomered as duck-typing (clearly it should be nomed quack-typing).

--
Neil Cerutti <mr.cerut...@gmail.com>

Guillermo

unread,
Mar 9, 2008, 8:20:41 AM3/9/08
to

>A protocol is just an interface that an object agrees to implement. In
>your case, you would state that every object stored in your special
>dict must implement the to_tagged_value method with certain agreeable
>semantics.

Hm... I've searched about the implementation of protocols and now (I
believe) I know how to implement the iterable protocol, for instance,
but have no clue about how to define my own... I'm surely not thinking
the right way, but I don't seem to be able to wrap my head around the
implementation details of "custom" protocols... Is it just a matter of
extending the different object classes (dict, list, tuple...)? Where
do you put the interface/protocol code? :-?

Regards,

Guillermo

Steven D'Aprano

unread,
Mar 9, 2008, 9:13:48 AM3/9/08
to


A protocol is a convention that you insist other objects must follow, not
code. To implement that convention, naturally you need to write code, but
the convention makes the protocol, not the code.

Some examples:

To be considered a writable file, your object must include a write()
method and a close() method. It doesn't matter what those methods do
exactly, so long as they behave reasonably. For instance, the close()
method might do nothing, and the write() method might send an SMS.

To be a random-access writable file, it must also include a seek() method.

To be a sequence, your object must obey the sequence protocol, which says
it has a __getitem__ method which takes integer arguments starting at 0
and increasing, until it raises IndexError.

You don't have to write any code to create a protocol, you just have to
tell people what it is. Here's my parrot protocol:


To be a parrot, your object must have a method speak() which takes an
integer argument and returns the case-insensitive string "spam" repeated
that many times.


I'm done. I have a protocol. But if I want to actually use it, then I
need an object that obeys it, and if I can't wait for somebody else to
write it, I need to write one myself. So here it is:

class Viking(object):
def __init__(self, case='upper'):
if case == 'upper':
self.case = str.upper
else:
self.case = str.lower
def speak(self, n):
return self.case("spam"*n)


And now Viking instances are also parrots, or rather, they obey the
parrot protocol:

>>> v = Viking()
>>> v.speak(3)
'SPAMSPAMSPAM'


I hope this helps.


--
Steven

Guillermo

unread,
Mar 9, 2008, 9:58:15 AM3/9/08
to

Mamma mia! My head just exploded. I've seen the light.

So you only need to ·want· to have a protocol? That's amazing... Far
beyond the claim that Python is easy. You define protocols in writing
basically! Even my grandma could have her own Python protocol.

Okay, so I think I know where's the catch now -- you must rely on the
fact that the protocol is implemented, there's no way to enforce it if
you're expecting a parrot-like object. You'd try to call the speak()
method and deal with the error if there's no such method?

Thanks a lot!

Guillermo

Steven D'Aprano

unread,
Mar 9, 2008, 10:23:25 AM3/9/08
to
On Sun, 09 Mar 2008 06:58:15 -0700, Guillermo wrote:

> Okay, so I think I know where's the catch now -- you must rely on the
> fact that the protocol is implemented, there's no way to enforce it if
> you're expecting a parrot-like object. You'd try to call the speak()
> method and deal with the error if there's no such method?

That's right. That's called "duck typing" -- if all you want is something
that quacks like a duck, then it doesn't matter if it actually is a duck
or not.

Or if you prefer: if it quacks like a duck and swims like a duck, then
it's close enough to a duck as to make no difference.


Sometimes though, you need to check for a parrot up front. So I'd so this:

try:
something.speak
except AttributeError:
# No speak() method, so it can't be a parrot.
do_something_else()
else:
# It seems to follow the parrot protocol.
yummy_goodness = something.speak(5)
assert "spam" in yummy_goodness.lower()


--
Steven

casti...@gmail.com

unread,
Mar 9, 2008, 4:58:15 PM3/9/08
to
On Mar 9, 9:23 am, Steven D'Aprano <st...@REMOVE-THIS-

cybersource.com.au> wrote:
> On Sun, 09 Mar 2008 06:58:15 -0700, Guillermo wrote:
> > Okay, so I think I know where's the catch now -- you must rely on the
> > fact that the protocol is implemented, there's no way to enforce it if
> > you're expecting a parrot-like object. You'd try to call the speak()
> > method and deal with the error if there's no such method?
>
> That's right. That's called "duck typing" -- if all you want is something
> that quacks like a duck, then it doesn't matter if it actually is a duck
> or not.
>
> Or if you prefer: if it quacks like a duck and swims like a duck, then
> it's close enough to a duck as to make no difference.

The syntax checker over here raised a warning on this one. "So close
to a duck as." (I'm using the so...as construct in my Propositional
Calculus program.)

> try:
>     something.speak
> except AttributeError:
>     # No speak() method, so it can't be a parrot.
>     do_something_else()

It might be a dead parrot. HAR!

> else:
>     # It seems to follow the parrot protocol.
>     yummy_goodness = something.speak(5)
>     assert "spam" in yummy_goodness.lower()

P.S. Is 'resemblant' a word? So resemblant of a duck as.

Gabriel Genellina

unread,
Mar 10, 2008, 12:45:46 AM3/10/08
to
On 9 mar, 11:23, Steven D'Aprano <st...@REMOVE-THIS-

cybersource.com.au> wrote:
> On Sun, 09 Mar 2008 06:58:15 -0700, Guillermo wrote:
> > Okay, so I think I know where's the catch now -- you must rely on the
> > fact that the protocol is implemented, there's no way to enforce it if
> > you're expecting a parrot-like object. You'd try to call the speak()
> > method and deal with the error if there's no such method?
>
> That's right. That's called "duck typing" -- if all you want is something
> that quacks like a duck, then it doesn't matter if it actually is a duck
> or not.

In addition to duck typing, in some cases an explicit declaration may
be useful: "I implement the Parrot protocol". The zope.interface
package does that: there is a way to define interfaces (a set of
methods any implementation must provide), and classes can assert "I
implement this interface", and one can determine whether a class
implements or not certain interface. See http://pypi.python.org/pypi/zope.interface

Abstract Base Classes (ABC, for Python 3.0) provide a similar concept
(but they're not the same thing). See http://www.python.org/dev/peps/pep-3119/

Of course there is some overlapping between all of these techniques -
one should choose the best method in each case.

--
Gabriel Genellina

Bruno Desthuilliers

unread,
Mar 10, 2008, 4:59:37 AM3/10/08
to
Guillermo a écrit :

> Mamma mia! My head just exploded. I've seen the light.
>
> So you only need to ·want· to have a protocol? That's amazing... Far
> beyond the claim that Python is easy. You define protocols in writing
> basically! Even my grandma could have her own Python protocol.
>
> Okay, so I think I know where's the catch now -- you must rely on the
> fact that the protocol is implemented,

Indeed. But even with static declarative typing ŕ la Java, you must rely
on the fact that the protocol is *correctly* implemented (what about
having file.close sending mails to all your contacts and then rebooting
the computer ?-). IOW, at some point, you have to trust the coder anyway.

> there's no way to enforce it if
> you're expecting a parrot-like object.

Yes there is:

> You'd try to call the speak()
> method

That's it.

> and deal with the error if there's no such method?

Either catch the AttributeError and raise a TypeError or ValueError (or
some more specific one) instead, or just let the AttributeError
propagate - whichever makes more sens given the context. I'd say the
default would be to catch the AttributeError and raise a TypeError
instead (that's at least what len() does when passed an unsized object).


Andrew Koenig

unread,
Mar 10, 2008, 10:29:48 AM3/10/08
to
>> if type(a) is dict:
>> print "a is a dictionnary!"

> class MyDict(dict):
> pass

> a = MyDict()

> type(a) is dict
> => False

isinstance(a, dict)
=> True

So the question you need to answer is whether you want to determine whether
an object is exactly of type dict, or whether it you are willing to accept
types derived from dict also.


Steven D'Aprano

unread,
Mar 10, 2008, 12:37:04 PM3/10/08
to
On Mon, 10 Mar 2008 14:29:48 +0000, Andrew Koenig wrote:

> So the question you need to answer is whether you want to determine
> whether an object is exactly of type dict, or whether it you are willing
> to accept types derived from dict also.

Or other mappings that don't inherit from dict but behave just like
dicts, such as UserDict.


--
Steven

0 new messages