Removing types module from stdlib

Should I start converting/removing uses of the types module where possible?
So where we have: assert type(lineno) is types.IntType assert type(lineno) in (types.IntType, types.LongType)
would become: assert type(lineno) is int assert type(lineno) in (int, long)
or assert isinstance(lineno, int) assert isinstance(lineno, (int, long))
Preferences?
Neal

Should I start converting/removing uses of the types module where possible?
Go ahead, but don't be too aggressive. I.e. leave cases where it's unclear what to do alone, and don't strive for completeness. OTOH, I see no need to go through the SF patch manager for this, as long as the test suite runs.
So where we have: assert type(lineno) is types.IntType assert type(lineno) in (types.IntType, types.LongType)
would become: assert type(lineno) is int assert type(lineno) in (int, long)
or assert isinstance(lineno, int) assert isinstance(lineno, (int, long))
Preferences?
I strongly prefer the isinstance() forms, but beware that they have different semantics in the light of subtypes. You may have to think about what's intended. Usually isinstance() will be the right thing to do though.
--Guido van Rossum (home page: http://www.python.org/~guido/)

There were a couple of threads on comp.lang.py with headings like "isinstance considered harmful". The conclusion was that most cases should have been coded some other way. The legitimate uses included implementing multiple dispatch (supporting calls with type differentiated signatures) , factory functions, decorator pattern (which needs to know if the object was previously decorated), and the composite pattern (which needs to know if it is dealing with an atom or a composite).
Here are some of the ideas for conversion:
if type(x) is int --> if x==int(x) # 3L would be passable
if type(x) == types.FileType --> if hasattr(x, 'read') # StringIO would work
if type(x) is str: x = x.lower() -->
try: x = x.lower() except AttributeError: pass
If the type check is meant to verify that an interface is supported, the try/except form maximized substitutability of objects which simulate the interface (like a UserDict or Shelve in place of a dictionary).
I'm not sure this kind of conversion should be done everywhere but it could be an opportunity to remove unnecessary type dependencies.
Raymond Hettinger
----- Original Message ----- From: "Neal Norwitz" neal@metaslash.com To: python-dev@python.org Sent: Friday, May 31, 2002 10:08 AM Subject: [Python-Dev] Removing types module from stdlib
Should I start converting/removing uses of the types module where
possible?
So where we have: assert type(lineno) is types.IntType assert type(lineno) in (types.IntType, types.LongType)
would become: assert type(lineno) is int assert type(lineno) in (int, long)
or assert isinstance(lineno, int) assert isinstance(lineno, (int, long))
Preferences?
Neal
Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev

raymond wrote:
There were a couple of threads on comp.lang.py with headings like "isinstance considered harmful". The conclusion was that most cases should have been coded some other way. The legitimate uses included implementing multiple dispatch (supporting calls with type differentiated signatures) , factory functions, decorator pattern (which needs to know if the object was previously decorated), and the composite pattern (which needs to know if it is dealing with an atom or a composite).
since when is comp.lang.py is an authority on anything?
Here are some of the ideas for conversion:
if type(x) is int --> if x==int(x) # 3L would be passable
are these supposed to be equivalent, for any kind of x? what Python version are you using?
</F>

There were a couple of threads on comp.lang.py with headings like "isinstance considered harmful". The conclusion was that most cases should have been coded some other way. The legitimate uses included implementing multiple dispatch (supporting calls with type differentiated signatures) , factory functions, decorator pattern (which needs to know if the object was previously decorated), and the composite pattern (which needs to know if it is dealing with an atom or a composite).
Missing from the list is the important use case where it is known that something you are going to do only works for a specific built-in type. E.g. marshal.dump() requires a real file (and no, don't bother "fixing" this -- marshal is sufficiently close to the implementation that I don't want it to be fixed). There are also places where a built-in int is required.
Here are some of the ideas for conversion:
if type(x) is int --> if x==int(x) # 3L would be passable
-1. This dies with a TypeError if x can't be converted to int.
if type(x) == types.FileType --> if hasattr(x, 'read') # StringIO would work
If that's what you want. But you should test for the method you're actually going to call, often readline, or write. (Don't test for multiple methods though -- that's too much).
if type(x) is str: x = x.lower() -->
try: x = x.lower() except AttributeError: pass
Hm, I hate to see try/except proliferated like this. Why is this needed in the first place? Can't you write "x = x.lower()" without the try/except?
If the type check is meant to verify that an interface is supported, the try/except form maximized substitutability of objects which simulate the interface (like a UserDict or Shelve in place of a dictionary).
In general I think explicit type checks are for wimps.
I'm not sure this kind of conversion should be done everywhere but it could be an opportunity to remove unnecessary type dependencies.
I'd be careful. Knowing what's right requires deep understanding of what the code is doing. If today it says type(x) is types.StringType, I'm comfortable that isinstance(x, str) will do the right thing; not about any of the alternatives.
I propose that if you find a place that looks like it is making too strict a type assertion, report it here or in the SF bug tracker before fixing it.
--Guido van Rossum (home page: http://www.python.org/~guido/)

Neal Norwitz neal@metaslash.com writes:
Should I start converting/removing uses of the types module where possible?
Would you like to review patch 562373. Walter already has some code for that.
Regards, Martin

"Martin v. Loewis" wrote:
Neal Norwitz neal@metaslash.com writes:
Should I start converting/removing uses of the types module where possible?
Would you like to review patch 562373. Walter already has some code for that.
Reviewing now... So far so good, but it brings up a question.
There was talk about changing string (the base class) to something else since it was the same name as the module. Was there ever a decision made?
Since I expect confusion between string (the module) and string (the abstract class). The name issue is marginally related to what's described below.
Right now, if you derive a class from an instance (yes, this shouldn't work):
>>> class x(5): pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: int() takes at most 2 arguments (3 given)
This makes sense and is what I would expect.
But this is not what I would expect:
>>> import string >>> class newstr(string): pass ... # i would have expected this to raise a TypeError >>> x = newstr() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'module' object is not callable
Perhaps this error should be handled when the class is constructed rather than when instantiating an object?
Of course, you can't derive from the string class either:
>>> del string >>> print string <type 'string'> >>> class x(string): pass ... >>> y = x() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: The string type cannot be instantiated
Neal

There was talk about changing string (the base class) to something else since it was the same name as the module. Was there ever a decision made?
Oops, no. Let's call it basestring. Can you do that?
Since I expect confusion between string (the module) and string (the abstract class). The name issue is marginally related to what's described below.
Right now, if you derive a class from an instance (yes, this shouldn't work):
class x(5): pass
... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: int() takes at most 2 arguments (3 given)
This makes sense and is what I would expect.
But this is not what I would expect:
import string class newstr(string): pass
... # i would have expected this to raise a TypeError
x = newstr()
Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'module' object is not callable
Perhaps this error should be handled when the class is constructed rather than when instantiating an object?
Can you submit a SF bug report for this? It has nothing to do with string per se -- the bug is that you can use any module as a base class. :-(
Of course, you can't derive from the string class either:
del string print string
<type 'string'>
class x(string): pass
...
y = x()
Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: The string type cannot be instantiated
Thinking a little about this, I think this is how I want it to be. str and unicode have special status and it shouldn't be easy to create something else (not deriving from either) that also gets this special status. (You can still do it in C of course.)
--Guido van Rossum (home page: http://www.python.org/~guido/)

Guido van Rossum wrote:
There was talk about changing string (the base class) to something else since it was the same name as the module. Was there ever a decision made?
Oops, no. Let's call it basestring. Can you do that?
Will do.
But this is not what I would expect:
>>> import string >>> class newstr(string): pass ... # i would have expected this to raise a TypeError >>> x = newstr() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: 'module' object is not callable
Perhaps this error should be handled when the class is constructed rather than when instantiating an object?
Can you submit a SF bug report for this? It has nothing to do with string per se -- the bug is that you can use any module as a base class. :-(
Will do.
Neal

On Fri, 31 May 2002, Guido van Rossum wrote:
str and unicode have special status and it shouldn't be easy to create something else (not deriving from either) that also gets this special status. (You can still do it in C of course.)
I use this little toy on occasion:
class istr(str): __slots__ = () def __hash__(self): return hash(self.lower()) def __eq__(self, other): return self.lower() == other.lower() def __ne__(self, other): return self.lower() != other.lower() def __le__(self, other): return self.lower() <= other.lower() def __ge__(self, other): return self.lower() >= other.lower() def __lt__(self, other): return self.lower() < other.lower() def __gt__(self, other): return self.lower() > other.lower()
Are you saying that you want to outlaw it?
-Kevin
-- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

I use this little toy on occasion:
class istr(str): __slots__ = () def __hash__(self): return hash(self.lower()) def __eq__(self, other): return self.lower() == other.lower() def __ne__(self, other): return self.lower() != other.lower() def __le__(self, other): return self.lower() <= other.lower() def __ge__(self, other): return self.lower() >= other.lower() def __lt__(self, other): return self.lower() < other.lower() def __gt__(self, other): return self.lower() > other.lower()
Are you saying that you want to outlaw it?
No, subclassing str (or unicode) is fine, because then you inherit the implementation properties.
I want to outlaw (or at least discourage) creating new subclasses of the basestring type (in current CVS it's called string, but it will be renamed soon).
If someone writes isinstance(x, basestring) they should be confident that x is either a str, a unicode, an instance of a subclass of those, or something written in C that works real hard to look like a string.
--Guido van Rossum (home page: http://www.python.org/~guido/)

On Fri, 31 May 2002, Guido van Rossum wrote:
I want to outlaw (or at least discourage) creating new subclasses of the basestring type (in current CVS it's called string, but it will be renamed soon).
Ah -- I knew I was missing something fundamental.
Thanks, -Kevin
PS: I like stringbase better than basestring. Not that it matters much.
-- Kevin Jacobs The OPAL Group - Enterprise Systems Architect Voice: (216) 986-0710 x 19 E-mail: jacobs@theopalgroup.com Fax: (216) 986-0714 WWW: http://www.theopalgroup.com

PS: I like stringbase better than basestring. Not that it matters much.
Both conventions occur with roughly the same frequency in the standard library. I'm not sure I favor either one.
--Guido van Rossum (home page: http://www.python.org/~guido/)
participants (6)
-
Fredrik Lundh
-
Guido van Rossum
-
Kevin Jacobs
-
martin@v.loewis.de
-
Neal Norwitz
-
Raymond Hettinger