views:

121

answers:

7

Hello,

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)?

A: 

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

if isinstance(item, str):
   # do your thing
Eli Bendersky
+1  A: 

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).
KennyTM
thank you v. much , Jasper
Jasper
A "better way" is not to typecheck!
Mike Graham
+5  A: 

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.

Xolve
+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
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.
Paul Hankin
+3  A: 

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.

Casey Duncan
raise an exception?????
Jasper
@Jasper, http://docs.python.org/tutorial/errors.html
Mike Graham
A: 

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.

bebraw
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 `TypeError`with no typechecking and `foo(1, 2)` *should work* with what foo does but doesn't because of typechecking
Mike Graham
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.)
Mike Graham
A: 

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)
...
Paul Hankin
Note that "genuine precondition" doesn't occur often in well-designed code as most people who are typechecking think it does.
Mike Graham
A: 

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

Johannes Lund