13

I have a function in a Python class that adds Interfaces to a list.

def RegisterAsListener(self, inListener):
    self.__TransitListeners.append(inListener)

This is nice, because a class just needs to inherit from said my Interface, grab this object, and register itself for all updates.

class ITransit():
    def TransitUpdate(self, data):
        raise NotImplementedError("You must define this function.")

(assuming I made an interface correctly)

Since i'm not the only one on this project, I don't want somebody calling the RegisterAsListener function with an incorrect data type. I could put in code to check the type within the register function, but it would be easier all around if the compiler just yelled at the programmer when they try to shove in an incorrect data type.

def RegisterAsListener(self, IListener inListener):
    self.__TransitListeners.append(inListener)

Is there any way to do this?

3
  • 14
    if the compiler just yelled at the programmer ... what compiler? Commented Feb 13, 2013 at 16:29
  • 2
    Use the abc module to define what an object should implement instead. Commented Feb 13, 2013 at 16:29
  • Otherwise, Python is a dynamically typed language, it does not enforce object types for you. Commented Feb 13, 2013 at 16:29

2 Answers 2

8

Although I would strongly recommend not doing this and only enforcing the implementation of certain methods using Abstract Base Classes (http://docs.python.org/2/library/abc.html), it is possible.

Here's an example on how to do something like that: http://www.artima.com/weblogs/viewpost.jsp?thread=101605

# mm.py
registry = {}                                                                   

class MultiMethod(object):                                                      
    def __init__(self, name):                                                   
        self.name = name                                                        
        self.typemap = {}                                                       
    def __call__(self, *args):                                                  
        types = tuple(arg.__class__ for arg in args) # a generator expression!  
        function = self.typemap.get(types)                                      
        if function is None:                                                    
            raise TypeError("no match")                                         
        return function(*args)                                                  
    def register(self, types, function):                                        
        if types in self.typemap:                                               
            raise TypeError("duplicate registration")                           
        self.typemap[types] = function                                          

def multimethod(*types):                                                        
    def register(function):                                                     
        function = getattr(function, "__lastreg__", function)                   
        name = function.__name__                                                
        mm = registry.get(name)                                                 
        if mm is None:                                                          
            mm = registry[name] = MultiMethod(name)                             
        mm.register(types, function)                                            
        mm.__lastreg__ = function                                               
        return mm                                                               
    return register                                                             

    if hasattr(function, "__lastreg__"):                                        
        function = function.__lastreg__

And the code using it:

import mm                                                                       

@mm.multimethod(int)                                                            
def spam(a):                                                                    
    print 'Calling the int method'                                              
    print '%s: %r' % (type(a), a)                                               

@mm.multimethod(float)                                                          
def spam(a):                                                                    
    print 'Calling the float method'                                            
    print '%s: %r' % (type(a), a)                                               

spam(5)                                                                         
spam(5.0)

Example output:

Calling the int method
<type 'int'>: 5
Calling the float method
<type 'float'>: 5.0
Sign up to request clarification or add additional context in comments.

1 Comment

Logical answer, if the question was asking how to enforce data types why does everyone say DON'T, PYTHON is DYNAMIC. You don't always have control on what objects you will receive so this is a very reasonable question.
7

Since i'm not the only one on this project, I don't want somebody calling the RegisterAsListener function with an incorrect data type

Document the function thoroughly, then let incorrect parameters throw exceptions. The user of RegisterAListener should be able to use the documentation to know what kind of data the function expects, and - if given incorrect parameters - the resulting exception should make it clear what the user of RegisterAListener did wrong.

2 Comments

You might consider using Python Annotations as part of documentation as a sort of self-documentation.
Logical answer, if the question was asking how to enforce data types why does everyone say DON'T, PYTHON is DYNAMIC. You don't always have control on what objects you will receive so this is a very reasonable question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.