Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function polymorphism in Python

I've been looking around for the best way of doing this but I haven't really found anything completely convincing.

I am writing a system where you have User objects and a collection that manages those Users. Each User has a name and I want to specify a function in the manager that can either take the name of the User or the User object itself.

class UserManager: 
  def remove_user(self,user_or_username):
    #If user_or_username is a string
    remote.remove(user_or_username)
    #If user_or_username is a User object
    remote.remove(user_or_username.name)

Is there any nifty way of doing this or is usage of isinstance the way to go?

like image 408
Parham Avatar asked May 15 '12 12:05

Parham


3 Answers

A solution like mgilson's, but slightly different:

def remove_user(self,user_or_username):
    try:
        #If user_or_username is a User object
        username = user_or_username.name
    except AttributeError:   #Oops -- didn't works.  ask forgiveness ;-)
        #If user_or_username is a string
        username = user_or_username
    remote.remove(username)

Why? Because this way, AttributeErrors in remove() are not suppressed.

It might be irrelevant, but I prefer concentrating exception handling to those places I really inted to have them.

like image 175
glglgl Avatar answered Sep 28 '22 06:09

glglgl


using isinstance is a good approach... There is one more approach for this solution

if hasattr(user_or_username, 'name'):
    # this object has <name> attribute
    remote.remove(user_or_username.name)
else:
    remote.remove(user_or_username)
like image 42
FallenAngel Avatar answered Sep 28 '22 05:09

FallenAngel


Sometimes python people like to say "it's better to ask forgiveness than permission"...

  def remove_user(self,user_or_username):
    try:
        #If user_or_username is a User object
        remote.remove(user_or_username.name)
    except AttributeError:   #Oops -- didn't works.  ask forgiveness ;-)
        #If user_or_username is a string
        remote.remove(user_or_username)

But I say it's just a matter of preference really. You could also use isinstance just as easily if you know you're only going to be getting strings, or User instances.

like image 42
mgilson Avatar answered Sep 28 '22 05:09

mgilson