2012-05-15 2 views
4

Я искал лучший способ сделать это, но я действительно не нашел ничего абсолютно убедительного.Функциональный полиморфизм в Python

Я пишу систему, в которой у вас есть объекты Пользователя и коллекция, которая управляет этими Пользователями. У каждого пользователя есть имя, и я хочу указать функцию в менеджере, которая может либо взять имя пользователя, либо сам объект пользователя.

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) 

Есть ли какой-нибудь отличный способ сделать это или использовать isinstance способ пойти?

+0

Да, 'isinstance' должно быть в порядке. –

+0

Полиморфизм действительно помогает, если вы не знаете в точке вызова, есть ли у вас имя или пользовательский объект. В основном это не так. Вы должны противостоять искушению перегружать функции, если вам действительно не нужно. Здесь у вас есть метод, который при задании строки просто привязывает к другому методу. Это запах кода: вы должны просто вызвать другой метод напрямую; когда у вас есть имя пользователя 'manager.remove (имя пользователя)' непосредственно. – Duncan

+0

Ваша точка действительна @Duncan, но в этом случае менеджер является промежуточным слоем, и его задача состоит в том, чтобы сделать правильные запросы для пользователя моего приложения. Я хотел изучить этот вариант, чтобы узнать, какую гибкость я имел в своем распоряжении! – Parham

ответ

5

Раствор как mgilson's, но несколько отличается:

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) 

Почему? Потому что таким образом, AttributeError s в remove() не подавляются.

Это может быть неуместно, но я предпочитаю сосредоточиться на обработке исключений в тех местах, где я действительно хотел их иметь.

+0

Для еще лучшего факторинга вы можете рассмотреть возможность извлечения функции для блока try/except. Это может быть полезно и в других местах. –

+1

@KarlKnechtel Ну, 'username = getattr (user_or_username, 'name', user_or_username)' также будет способом ... – glglgl

+0

Хорошая точка сосредоточения обработки исключений. – mgilson

2

Иногда Python люди, как говорят, «что лучше просить прощения, чем разрешения» ...

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) 

Но я говорю, что это просто вопрос предпочтения действительно. Вы также можете использовать isinstance так же легко, если знаете, что получите только строки, или User экземпляров.

2

Я хотел бы использовать isinstance, но это также работает:

def remove_user(self, user): 
    if hasattr(user, "name"): 
     self.remove(user.name) 
    else: 
     self.remove(user) 
3

isinstance используя хороший подход ... Существует еще один подход к этому решению

if hasattr(user_or_username, 'name'): 
    # this object has <name> attribute 
    remote.remove(user_or_username.name) 
else: 
    remote.remove(user_or_username) 
Смежные вопросы