dil: (Default)
dil ([personal profile] dil) wrote2009-06-25 12:52 pm

Журналюги такие журналюги…

Для тех, кто не в курсе: фамилия Рустема – Адагамов.

А Агдам – это дешёвое креплёное вино, названное в честь города в Карабахе :)

Оригинал этой записи в личном блоге.
Любые материалы из этого блога запрещается использовать на сайте livejournal.ru в любой форме и любом объёме.

[identity profile] shigin.livejournal.com 2009-10-08 03:15 pm (UTC)(link)
Я плохо знаком с Джангой, но выскажусь:

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

2. Затраты на декоратор минимальны. Если такие вещи критичны, надо брать другой язык.

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

[identity profile] dil.livejournal.com 2009-10-08 03:18 pm (UTC)(link)
1. Не понял.

2. Они, конечно, минимальны, но есть. А пользы от них я никакой не вижу.

3. Тоже не понял. Можно первый и третий пункт поподробнее?

[identity profile] motto.livejournal.com 2009-10-08 03:31 pm (UTC)(link)
http://en.wikipedia.org/wiki/Decorator_pattern

Там кстати, практически твой пример прописан :)

[identity profile] dil.livejournal.com 2009-10-08 03:41 pm (UTC)(link)
а зачем в данном конкретном случае _динамическое_ навешивание функциональности? вся нужная функциональность известна заранее, вполне реализуется статически. тут задача была только в вынесении общего куска кода в единое место.
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-10-10 02:44 pm (UTC)(link)
ничего более "динамического", чем при любой операции в питоне, тут нет. функции строятся один раз, а меняются только замыкания. отличие от твоего метода, грубо говоря, в том, что вместо
requires_login, {'view': my_view1}
получается
{'code': requires_login, 'view': my_view1}
только объект имеет тип не dict, а function.

[identity profile] dil.livejournal.com 2009-10-10 09:43 pm (UTC)(link)
да, это я ещё не вкурил замыкания :(
ext_659502: (Default)

[identity profile] some41.livejournal.com 2009-10-11 11:41 am (UTC)(link)
другой способ смотреть на вещи:
class View1:
  def __call__(this, request):
    # some code

view1 = View1()
# called as view1(request), same for view2, view3

# one way
class RequiresLogin1:
  def __call__(this, view, request):
    if somecheck:
      return something
    return view(request)

requeres_login = RequiresLogin1()
# called as requeres_login(view1, request)
# ... requeres_login(view2, request), requeres_login(view3, request)

# another way
class RequiresLogin2:
  def __init__(self, view):
    self.view = view
  def __call__(self, request):
    if somecheck:
      return something
    return self.view(request)

rview1 = RequiresLogin2(view1)
# called as rview1(request), same for view2, view3

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

[identity profile] shigin.livejournal.com 2009-10-08 03:42 pm (UTC)(link)
1. Декотраторы --- это такой простой способ "обернуть" функцию дополнительным функционалом или проверками. В нашем случае это будет выглядить как:
@requires_login
def my_view3(request):
    # ...
    return render_to_response('template3.html')
Что абсолютно эквивалентно:
def my_view3(request):
    # ...
    return render_to_response('template3.html')
my_view3 = requires_login(my_view3)


2. Я думаю, что расходы сравнимы с созданием словаря и ** на каждый запрос (я плохо помню cpython api в этом месте).

3. Я повторюсь, что не знаю как принято в джанге, но я подозреваю, что все стандартные view'хи выглядят как name(request). В каких-то случаях, я подозреваю, имеет смысл вызвать код view из своего кода. В этом случае, когда одному view нужен дополнительный параметр, а каким-то нет будет мешать. Но на этом пункте я не настаиваю.

[identity profile] bormotov.livejournal.com 2009-10-08 04:17 pm (UTC)(link)
поддержу пп.3
тоже не знаю джанги :)

[identity profile] shigin.livejournal.com 2009-10-08 03:57 pm (UTC)(link)
Брр... Болею, поэтому торможу. Никакого "динамического создания функции" тут не происходит. Функция одна, просто замыкания у них разные:
In [24]: def wrap(f, k):
    def inner(*arg, **kwargs):
        print("start", k)
        return f(*arg, **kwargs)
    return inner
   ....: 

In [29]: x = wrap(min, 1)

In [30]: y = wrap(max, 2)

In [31]: x.func_closure is y.func_closure
Out[31]: False

In [32]: x.func_code is y.func_code
Out[32]: True