2013-07-03 3 views
1

Я пишу следующее для создания URL-адреса для моего urls.py:Получить объект класса из строки

urls = { 
    'overview': { 
     r'^$':   [ 'Index' ], 
     r'^/account$': [ 'Account' ], 
    }, 

    'content': { 
     r'^/content$':  [ 'Index' ] 
     r'^/content/upload$': [ 'Uploader', 'Default' ] 
    } 

} 

urlpatterns = patterns('') 

for module, spec in urls.iteritems(): 
    urlpatterns += patterns('views.'+ module, 
     [ 
       url(regex, (getattr(module.capitalize() , 'as_view'))(), action=view[0]) 
      if len(view) == 1 else 
       url(regex, (getattr(view[0], 'as_view'))(), action=view[1]) 
      for regex, view in spec.iteritems() 
     ] 
    ) 

У меня есть модули overview и content, с классами Overview и Content и Uploader соответственно.

Если view массива (например, [ 'Index' ] содержит один элемент, я использую заглавную форму модуля (например, overview становится Overview) для генерации маршрута:

url(r'^$', Overview.as_view(), action='Index') 

, тогда как, если оно содержит два элемента (например, [ 'Uploader', 'Default' ]), то первый элемент определяет имя класса, а второй метод:

url(r'^$', Uploader.as_view(), action='Default') 

Как вы уже заметили, вопрос с моим использованием getattr(), чей первый аргумент требует ссылки на класс. Итак, мой вопрос: , есть ли способ получить объект класса из строки, которая содержит идентификатор указанного объекта класса, например, класс Uploader от 'Uploader'.

Как отказ от ответственности, это не мои точные маршруты, просто пример. И, конечно, дальнейшие комментарии приветствуются и в отношении моего общего дизайна здесь.

ответ

3

Я бы сказал, что есть два общих способа сделать это. Рассмотрим пример ниже:

from random import choice 


class A(object): 
    def __init__(self): 
     self.name = 'in A' 


class B(object): 
    def __init__(self): 
     self.name = 'in B' 


class C(object): 
    def __init__(self): 
     self.name = 'in C' 

if __name__ == "__main__": 
    classes = ['A', 'B', 'C'] 
    class_name = choice(classes) 
    print class_name 

    # 1st way 
    obj = globals()[class_name]() 
    print obj.name 

    # 2nd way 
    import sys 
    obj = getattr(sys.modules['__main__'], class_name)() 
    print obj.name 

    # 3rd way - not recommended 
    obj = eval(class_name)() 
    print obj.name 
+0

А, интересно. Итак, что касается второго способа, заключается в том, что 'getattr' может работать не только с классами/объектами (а именно с« таблицей символов »модуля' __main__'), либо это то, что модули и классы на самом деле одинаковы природа? (Быть, что у них обоих есть атрибуты). Спасибо, кстати! –

+0

Помните, что все в Python - это объект, даже модуль;) – matino

+0

О, хорошо, круто. Итак, как разработчики языка Python избегали дорогостоящего снижения производительности с помощью такого объектно-ориентированного подхода? Полагаю, я могу просто взглянуть на это сейчас, хотя .. –

Смежные вопросы