November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Thursday, June 25th, 2009 12:52 pm

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

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

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

Thursday, October 8th, 2009 03:15 pm (UTC)
Я плохо знаком с Джангой, но выскажусь:

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

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

3. Получается, что разные обработчики теперь имеют разные сигнатуры. Это не очень прикольно, если вызывать обработчики самому (понятия не имею, имеет ли это смысл в джанге). Я предпочитаю, что бы у одинаковые функции имели одинаковые соглашения о вызовах.
Thursday, October 8th, 2009 03:18 pm (UTC)
1. Не понял.

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

3. Тоже не понял. Можно первый и третий пункт поподробнее?
Thursday, October 8th, 2009 03:31 pm (UTC)
http://en.wikipedia.org/wiki/Decorator_pattern

Там кстати, практически твой пример прописан :)
Thursday, October 8th, 2009 03:41 pm (UTC)
а зачем в данном конкретном случае _динамическое_ навешивание функциональности? вся нужная функциональность известна заранее, вполне реализуется статически. тут задача была только в вынесении общего куска кода в единое место.
Saturday, October 10th, 2009 02:44 pm (UTC)
ничего более "динамического", чем при любой операции в питоне, тут нет. функции строятся один раз, а меняются только замыкания. отличие от твоего метода, грубо говоря, в том, что вместо
requires_login, {'view': my_view1}
получается
{'code': requires_login, 'view': my_view1}
только объект имеет тип не dict, а function.
Saturday, October 10th, 2009 09:43 pm (UTC)
да, это я ещё не вкурил замыкания :(
Sunday, October 11th, 2009 11:41 am (UTC)
другой способ смотреть на вещи:
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

т.е. весь накладной расход на второй вариант, это создание нескольких копеечных объектов, зато мы сохраняем полную совместимость по интерфейсу.
Thursday, October 8th, 2009 03:42 pm (UTC)
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 нужен дополнительный параметр, а каким-то нет будет мешать. Но на этом пункте я не настаиваю.
Thursday, October 8th, 2009 04:17 pm (UTC)
поддержу пп.3
тоже не знаю джанги :)
Thursday, October 8th, 2009 03:57 pm (UTC)
Брр... Болею, поэтому торможу. Никакого "динамического создания функции" тут не происходит. Функция одна, просто замыкания у них разные:
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