3

I'm creating an initialising function for the class 'Room', and found that the program wouldn't accept the tests I was doing on the input variables.

Why is this?

def __init__(self, code, name, type, size, description, objects, exits):
    self.code = code
    self.name = name
    self.type = type
    self.size = size
    self.description = description
    self.objects = objects
    self.exits = exits
            #Check for input errors:
    if type(self.code) != type(str()):
        print 'Error found in module rooms.py!'
        print 'Error number: 110'
    elif type(self.name) != type(str()):
        print 'Error found in module rooms.py!'
        print 'Error number: 111'
    elif type(self.type) != type(str()):
        print 'Error found in module rooms.py!'
        print 'Error number: 112'
    elif type(self.size) != type(int()):
        print 'Error found in module rooms.py!'
        print 'Error number: 113'
    elif type(self.description) != type(str()):
        print 'Error found in module rooms.py!'
        print 'Error number: 114'
    elif type(self.objects) != type(list()):
        print 'Error found in module rooms.py!'
        print 'Error number: 115'
    elif type(self.exits) != type(tuple()):
        print 'Error found in module rooms.py!'
        print 'Error number: 116'

When I run this I get this error:

Traceback (most recent call last):
  File "/Users/Jasper/Development/Programming/MyProjects/Game Making Challenge/Europa   I/rooms.py", line 148, in <module>
    myRoom = Room(101, 'myRoom', 'Basic Room', 5, '<insert description>', myObjects, myExits)
  File "/Users/Jasper/Development/Programming/MyProjects/Game Making Challenge/Europa I/rooms.py", line 29, in __init__
    if type(self.code) != type(str()):
TypeError: 'str' object is not callable

---- Thanks for help, but: -----

does this apply for isinstance(item, list) or isinstance(item, tuple)?

3
  • 5
    Please Do Not Do This. All the type checking is a simple waste of time. If "somehow" the wrong type is used, your program will crash with a glorious and obvious error. You don't need this. Please do not do it.
    – S.Lott
    Commented Mar 20, 2010 at 12:28
  • 1
    How hard would it have been to investigate the answer yourself? How hard would it have been to reduce the example down to the bare minimum?
    – user97370
    Commented Mar 20, 2010 at 12:31
  • Jasper, the rest of checks are unreachable due to elif. Only one check will fail per time, the others you will discover later.
    – Tom Lime
    Commented Apr 21, 2013 at 6:59

7 Answers 7

13

Not answering the "why", but

  1. str itself is a type already. You can use type(self.code) != str
  2. But a better way is to use isinstance(self.code, str).
3
  • 1
    A "better way" is not to typecheck! Commented Mar 20, 2010 at 15:48
  • 11
    Not always. Some times you have to type check, say when encoding an object (think JSON). Commented Jul 8, 2012 at 6:07
  • you can print(self.code.dtype) to determine its data type Commented May 26, 2021 at 22:06
8

Python is a dynamic language. It bad idea to test the types explicitly. In fact the code you write should in itself be such that you dont ever need to test the types of variables.

If you are coming from C/C++/Java then takes some time to get over that.

2
  • 5
    +1: Do not test types. If they're wrong it will crash. On the other hand, they could be a new type, perfectly compatible, and you've prevented a perfectly compatible use case.
    – S.Lott
    Commented Mar 20, 2010 at 14:16
  • 2
    To make S. Lott's point concrete: the class posted would probably work fine with unicode strings were it not for the over-zealous typechecking.
    – user97370
    Commented Mar 20, 2010 at 16:25
3

Couple of things:

  • You have an incoming parameter named "type". This is masking the "type" built-in because it is a global, and locals trump globals. I assume this exception occurs because "type" has a string value.

  • Why are you printing error messages? The correct way to report an error is to raise an exception.

Overall I concur with the other answers that type-checking in general is a python anti-pattern. It it needed only in rare cases.

0
2

Beside the ideas presented before you might want to check out decorator based type checking and contracts.

Historically there has been some interest in integrating optional typing to the language.

There are specific extension languages, such as Cython and Pyrex, that pretty much force you to type to some extent in order. The cool thing is that these languages allow you to generate high performance C extensions to use with your regular Python code.

2
  • 1
    The examples at the decorator-based type checking recipe show why typechecking is so futile in Python. foo("asdf", 2.5) would already have raised TypeErrorwith no typechecking and foo(1, 2) should work with what foo does but doesn't because of typechecking Commented Mar 20, 2010 at 16:02
  • Note that Cython is pretty similar to Pyrex, except the former is more willing to move quickly in its development and make sacrifices in favour of practicality. For writing production code, the more pragmatic Cython is the more appropriate tools. (Use of either isn't really indicated by anything I see here, though.) Commented Mar 20, 2010 at 16:04
2

In general don't type-check, but if it's a genuine precondition for the arguments then verify them using assert rather than printing errors to stdout.

assert isinstance(code, str)
assert isinstance(name, str)
...
1
  • Note that "genuine precondition" doesn't occur often in well-designed code as most people who are typechecking think it does. Commented Mar 20, 2010 at 15:49
0

It's not a good idea testing for types like this. However, if you must, do:

if isinstance(item, str):
   # do your thing
0
-1

in python you just use the variables as if they where the type you want. if for some reason you have a function you call with different types, you can wrap your code in a try/catch.

def addOne(a):
    ''' 
    increments a with 1 if a is a number. 
    if a is a string, append '.' to it.    
    '''
    try:
        return a + 1
    except TypeError:
        return a + "."

but you generally dont want to do that. for the case above use to different functions