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

isMappingType

5 views
Skip to first unread message

Paul Prescod

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to
Is this right?

>>> import operator

>>> class foo:
>>> pass

>>> operator.isMappingType( foo() )
1

>>> operator.isSequenceType( foo() )
1

That doesn't look right to me...

Paul Prescod


Guido van Rossum

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to

You may have missed that isMappingType() and isSequenceType() are
undocumented. This is because they are obsolete. This, in turn, is
because they can't be made to work. There is no single test possible
to see whether an object is a mapping or a sequence: a class could
define only __getitem__ and you can't tell whether it's intended as a
mapping or a sequence (without calling it, that is).

--Guido van Rossum (home page: http://www.python.org/~guido/)


Paul Prescod

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to
On Mon, 24 Aug 1998, Guido van Rossum wrote:

> You may have missed that isMappingType() and isSequenceType() are
> undocumented. This is because they are obsolete. This, in turn, is
> because they can't be made to work.

I thought that they were "not yet documented." They strike me as of major
importance. Perhaps Python needs an explicit deprecation mechanism, as
Java has.

> There is no single test possible
> to see whether an object is a mapping or a sequence: a class could
> define only __getitem__ and you can't tell whether it's intended as a
> mapping or a sequence (without calling it, that is).

How about this:

if type( obj )==types.InstanceType:
return hasattr( obj, "__issequence__" )
else:
return whateverWeDoTodayWhichSeemsToWorkOkayForNonInstances()

Or else:

... return (sequence in obj.__protocols__)

Both of these depend on new conventions, so they won't fix old code, but
the sooner we implement the new conventions, the sooner this stuff works
reliably. Python's future seems closely tied to the success of protocols.

Paul Prescod

Guido van Rossum

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to
[me]

> > You may have missed that isMappingType() and isSequenceType() are
> > undocumented. This is because they are obsolete. This, in turn, is
> > because they can't be made to work.

[Paul]


> I thought that they were "not yet documented." They strike me as of major
> importance. Perhaps Python needs an explicit deprecation mechanism, as
> Java has.

Perhaps.

But why do you think they are of major importance? Type checks almost
always smell of un-OO coding.

> Python's future seems closely tied to the success of protocols.

Really? Got any evidence?

Michael T. Richter

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to
Guido van Rossum wrote in message
<1998082421...@eric.CNRI.Reston.Va.US>...

>Type checks almost always smell of un-OO coding.

In my RC4 class (http://www.igs.net/~mtr/python/rc4.html) I wanted
originally to use a type check to ensure that passed data was a sequence
type. There wasn't a reliable way to do this, unfortunately, so I gave up
on it and made this aspect of the class heavy duty "caveat utilitor": if you
don't pass me a string you're likely to get burned.

--
Michael T. Richter <m...@ottawa.com> http://www.igs.net/~mtr/
PGP Key: http://www.igs.net/~mtr/pgp-key.html
PGP Fingerprint: 40D1 33E0 F70B 6BB5 8353 4669 B4CC DD09 04ED 4FE8

Paul Prescod

unread,
Aug 24, 1998, 3:00:00 AM8/24/98
to
On Mon, 24 Aug 1998, Guido van Rossum wrote:

> But why do you think they are of major importance? Type checks almost

> always smell of un-OO coding.

Type checks smell to me of attempts to document and confirm programmer
intent. We get away without that in the Python world because we usually
compare Python to Perl and TCL, so Python's scalability and rigour is
impressive in comparison. But compared to Java, etc., it seems quite
weak. Protocols allow us to get some of that safety without the static
type checking constraints.

On the other hand, perhaps another way to "spell" protocol is
isInstance(). If you want to make something behave as a sequence, you
could inherit from UserSequence or UserList.

In any case, the particular use I had for them now is non-OO programming.
I want to extend the PyWin object browser to be able to display any
sequence or mapping type.

Paul Prescod


Jeff...@bigfoot.com

unread,
Aug 25, 1998, 3:00:00 AM8/25/98
to papr...@technologist.com
Paul Prescod <papr...@technologist.com> wrote:
> I thought that they were "not yet documented." They strike me as
> of major importance. Perhaps Python needs an explicit deprecation
> mechanism, as Java has.

This has been a minor issue for me too. Some time ago I wrote
a few thoughts on the starship:

http://starship.skyport.net/crew/jbauer/deprecate.html

It's probably worth adding some sort of entry to the Python
TODO list requesting support for a deprecation mechanism.

--
Jeff Bauer
Chief Safety Officer
Rubicon, Inc.

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum

Jeff...@bigfoot.com

unread,
Aug 25, 1998, 3:00:00 AM8/25/98
to
GvR >>Type checks almost always smell of un-OO coding.

mtr> In my RC4 class (http://www.igs.net/~mtr/python/rc4.html)
mtr> I wanted originally to use a type check to ensure that passed
mtr> data was a sequence type. There wasn't a reliable way to do
mtr> this, unfortunately, so I gave up on it and made this aspect
mtr> of the class heavy duty "caveat utilitor": if you don't pass
mtr> me a string you're likely to get burned.

The true path of OO cautions against type checking as
a general rule, but this notion is a little extreme to
apply in situations where an exception ought to be thrown.

For example, when a function expects a list or tuple of
objects, it isn't always clear that the user has erroneously
passed a string.

foo(('abc','def')) # pass a tuple
foo(('ghi')) # not a tuple, forgot trailing comma

Since the code will often happily perform many operations
against a string as a sequence (for x in arg, len(arg), etc.)
it can become time-consuming error to trace. A type check
that raises an exception is much more effective than the most
strident exhortation posted in the comments.

no-worse-than-assertions-heretically-yr's,

Michael McLay

unread,
Aug 25, 1998, 3:00:00 AM8/25/98
to
Jeff...@bigfoot.com writes:
> Paul Prescod <papr...@technologist.com> wrote:
> > I thought that they were "not yet documented." They strike me as
> > of major importance. Perhaps Python needs an explicit deprecation
> > mechanism, as Java has.
>
> This has been a minor issue for me too. Some time ago I wrote
> a few thoughts on the starship:
>
> http://starship.skyport.net/crew/jbauer/deprecate.html
>
> It's probably worth adding some sort of entry to the Python
> TODO list requesting support for a deprecation mechanism.

How about a convention of adding a __deprecate__ tuple immediately following
the __doc__ in things which are deprecated. The interpreter wouldn't
have to treat them specially for now, but eventually someone with the
itch could write a find_deprecated_code program to hunt down all the
things which have been deprecated and all uses of old code.

The value of __deprecate__ would be a tuple. The first field would be
a string timestamp of when it was deprecated. The second field would
be a description of why it was deprecated, and the third field would
be a suggested alternative to the deprecated code. The fourth field
would indicate the release version of python which would no longer
include the deprecated thing. The fifth field would be the name of the
person who deprecated it.)

John (Max) Skaller

unread,
Aug 26, 1998, 3:00:00 AM8/26/98
to
On Mon, 24 Aug 1998 21:29:35 GMT, Paul Prescod <papr...@technologist.com> wrote:
>> There is no single test possible
>> to see whether an object is a mapping or a sequence: a class could
>> define only __getitem__ and you can't tell whether it's intended as a
>> mapping or a sequence (without calling it, that is).
>
>How about this:
>
>if type( obj )==types.InstanceType:
> return hasattr( obj, "__issequence__" )
>else:
> return whateverWeDoTodayWhichSeemsToWorkOkayForNonInstances()
>
>Or else:
>
>... return (sequence in obj.__protocols__)
>
>Both of these depend on new conventions, so they won't fix old code, but
>the sooner we implement the new conventions, the sooner this stuff works
>reliably. Python's future seems closely tied to the success of protocols.

Check out my protocols module. Look in the resource guide at

http://www.triode.net.au/~skaller/interscript

John Max Skaller ph:61-2-96600850
mailto:ska...@maxtal.com.au 10/1 Toxteth Rd
http://www.maxtal.com.au/~skaller Glebe 2037 NSW AUSTRALIA

Greg Ewing

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to
Michael McLay wrote:
>
> How about a convention of adding a __deprecate__ tuple immediately following
> the __doc__ in things which are deprecated.

Urg! This seems to be taking syntax overloading a bit far.

I'd suggest giving it the form of a function call,
e.g.

def foo():
__deprecate__(date = "31 Dec 1999",
reason = "Not Y2K compliant", replacement = "blarg()",
disappears = "1.9.7", by = "Hapless J. Programmer")

This could be done now, with any desired action
happening in response to the use of deprecated
code. Future interpreters could recoginise it
for the sake of efficiency -- if we're even
concerned about how efficiently deprecated code
gets executed anyway.

--
Greg Ewing, Computer Science Dept, | The address below is not spam-
University of Canterbury, | protected, so as not to waste
Christchurch, New Zealand | the time of Guido van Rossum.
gr...@cosc.canterbury.ac.nz

Konrad HINSEN

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to
Guido van Rossum <gu...@CNRI.Reston.Va.US> writes:

> But why do you think they are of major importance? Type checks almost

> always smell of un-OO coding.

I use plenty of (home-made) type checks, exclusively for one type of
application: checking the parameters of a function/method.

Here's an example. I have a class "Collection" which represents a
collection of "MyObject" instances or subtypes. The method addObject
accepts either a suitable object or any sequence of such objects:

class MyObject:

is_myobject = 1

...

class Collection:

def __init__(self):
self.objectlist = []

def addObject(self, object):
if hasattr(object, 'is_myobject'):
self.objectlist.append(object)
else if isSequence(object):
for o in object:
self.addObject(o)
else:
raise TypeError, "illegal type"


For isSequence I use some heuristic function that works well enough
for me, but I'd much prefer something more "official" and of course
efficient. I don't see any way to get the same behaviour without
type checks, but I am open for suggestions!
--
-------------------------------------------------------------------------------
Konrad Hinsen | E-Mail: hin...@cnrs-orleans.fr
Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-2.38.25.55.69
Rue Charles Sadron | Fax: +33-2.38.63.15.17
45071 Orleans Cedex 2 | Deutsch/Esperanto/English/
France | Nederlands/Francais
-------------------------------------------------------------------------------

Konrad HINSEN

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to
Paul Prescod <papr...@technologist.com> writes:

> On the other hand, perhaps another way to "spell" protocol is
> isInstance(). If you want to make something behave as a sequence, you
> could inherit from UserSequence or UserList.

Except that you can't do that for the most frequently used sequence
types, i.e. lists and tuples!

jeff_...@my-dejanews.com

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to

>>Michael McLay:

>> How about a convention of adding a __deprecate__ tuple
>> immediately following the __doc__ in things which are
>> deprecated.

>Greg Ewing:


> Urg! This seems to be taking syntax overloading a bit far.
>
> I'd suggest giving it the form of a function call,
> e.g.
>
> def foo():
> __deprecate__(date = "31 Dec 1999",
> reason = "Not Y2K compliant", replacement = "blarg()",
> disappears = "1.9.7", by = "Hapless J. Programmer")
>
> This could be done now, with any desired action
> happening in response to the use of deprecated
> code. Future interpreters could recoginise it
> for the sake of efficiency -- if we're even
> concerned about how efficiently deprecated code
> gets executed anyway.

1. In an earlier version of Deprecate This!, I had considered
the possibility of using a function call. I have since
removed the argument in favor a of docstring due to potential
overhead problems, e.g. a deprecated method used in a tight
loop.

2. Providing a date or version number for when a piece of
deprecated code is often not practical. Although
xxx might be deprecated in favor of yyy, it's often
doubtful when (or if) anyone can predict that xxx will
be dropped.

3. What is deprecatible?
- classes
- functions
- methods
- public attributes (?)
- entire modules (?)

4. Regardless of the mechanism (docstring or function call),
marking a code segment as deprecated should start from a
minimum and allow features to creep in after the minimum
has been defined:

minimal: xxx() <-- deprecated
more: xxx() <-- deprecated by A on B because of C ...

I think this is what Greg implied by his use of keyword
arguments.

Paul Prescod

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to
Your proposal looks very complete, but after thinking for a while, I think
that I prefer a "query interface" based mechanism. A dictionary cannot be
directly used as a sequence, but it can give you a "sequence view" if you
ask it to. What do you think?

Paul Prescod - http://itrc.uwaterloo.ca/~papresco

"You have the wrong number."
"Eh? Isn't that the Odeon?"
"No, this is the Great Theater of Life. Admission is free, but the
taxation is mortal. You come when you can, and leave when you must. The
show is continuous. Good-night." -- Robertson Davies, "The Cunning Man"

John Skaller

unread,
Aug 27, 1998, 3:00:00 AM8/27/98
to
At 08:24 27/08/98 -0500, Paul Prescod wrote:
>Your proposal looks very complete, but after thinking for a while, I think
>that I prefer a "query interface" based mechanism. A dictionary cannot be
>directly used as a sequence, but it can give you a "sequence view" if you
>ask it to. What do you think?

Hmm. Are you refering to your proposal along the lines of
---->
Any object such that getattr( obj, "AsSequence" ) returns a callable
object is considered to be a sequence. By convention, the callable object
should, when called, return a "view" of the object that can be used as a
sequence. In simple cases, this will be:

def AsSequence( self ): return self
<-----

There's some merit in this idea. See below for detailed
discussion.

Executive summary: There is a problem.
An object x will support sequence protocol and permit:

for i in range(len(x)): do_something(x[i])

or not. There's no such thing as 'a' view of an object as a sequence.
Either the object _is_ a sequence, and supports the protocol, or it isn't.

What i mean is, that some object for which a sequence view
can be constructed isn't (necessarily) itself a sequence, indeed,
there may be _more than one_ sequence view of an object.

For example, a list is a sequence. But what is the
'asSequence' of a list? It itself is a sequence. So too is _every_
permutation thereof: for a list of length n there are n! permutations.
What about a tree? There are _lots_ of ways to view a tree as a sequence.

Advanced discussion
-------------------

In fact, these maps go from one category to another. Not every possible
map is functorial. But there can still be lots of distinct functors.

For example, consider the category in which the objects are
trees. Let's suppose the arrows of this category -- the maps from
one tree to another -- are those functions f for which if x <= y then
f(x) <= f(y) -- in other words, if an object (node) of a tree is a descendant
of another, then the images of these objects in the target tree
are also descendants. These are 'tree morphisms': maps that preserve
parent child relationships. (partial ordering)

The tree category consists of all the tree morphisms.
Note that the abstract notion of tree is defined by the structure
of these morphisms (and has nothing whatsoever to do with the actual
trees: this is a _true_ definition of an abstract data type in a way OO
can never do it).

Now, consider the category of sequences. The arrows of this
category are functions which preseve (total) ordering. Again, the structure
of this category _defines_ what a sequence is independently of any objects.
Again, this is true abstraction: it not only hides the representation
details of the data structures -- it throws the objects out completely.
Death to OO! :-)


Now what is a functor? It's a structure preserving map between
categories. Consider a map from the category of trees to the category
of sequences. (Note: this map assigns to _functions_ of the tree category,
_functions_ of the sequence category: the assignment of a tree to a sequence
is the trivial special case of the identity function)


So given two tree morphisms

f:T1-->T2 and g:T2-->T3 (so that f . g: T1 --> T3, I use reverse polish)

then for a functor F:trees --> sequences we must have

F(f .g) = F(f) . F(g)

Here's an example for F: 'depth_first_search'.
Here's another: 'breadth_first_search'.

[You will have to think about what this means very carefully! ]

My point is this: your proposal amounts to:

"For some category C, say a C is a D if there is a functor
from C to D, and give one such functor."

This is much more advanced and difficult .. as you can see from the discussion
above <grin> .. than my proposal which amounts to

"Is object c an identity arrow (object) of the category C?"

-------------------------------------------------------
John Skaller email: ska...@maxtal.com.au
http://www.maxtal.com.au/~skaller
phone: 61-2-96600850
snail: 10/1 Toxteth Rd, Glebe NSW 2037, Australia

Barry A. Warsaw

unread,
Aug 28, 1998, 3:00:00 AM8/28/98
to

>>>>> "J" == JeffBauer <Jeff...@bigfoot.com> writes:

J> Since the code will often happily perform many operations
J> against a string as a sequence (for x in arg, len(arg), etc.)
J> it can become time-consuming error to trace. A type check that
J> raises an exception is much more effective than the most
J> strident exhortation posted in the comments.

Reminds me of a buglet I just fixed. I couldn't figure out why the
following statement wasn't giving me the directory I wanted:

DEFAULT_PROVIDER_DIR = os.path.normpath(
os.path.join(rootdir,
'demos',
'provider'
'var',
'providers'))

Hint: type checking wouldn't have helped! ;-)

-Barry

0 new messages