On Sat, Oct 2, 2010 at 8:01 PM, Carl Meyer <carl.j.me...@gmail.com> wrote: > > > On Oct 2, 4:34 am, Russell Keith-Magee <russ...@keith-magee.com> > wrote: >> I can't argue with the fact that setting variables in __init__() is a >> common idiom in Python generally, and this is certainly a weakness of >> copy on call that will fail in non-thread safe ways. >> >> My counterclaim is that the move to class-based views is largely >> driven by a desire to discourage the use of arguments in this way. We >> want to discourage people from using arguments to class-based views, >> and use subclassing instead. > > Talking about __init__ arguments is a red herring: > > class Foo(View): > def __init__(self): > self.bar = [] > self.baz = {} > > I can't count the number of times I've done this; can you? This is an > outright failure mode for copy-on-call; no __init__ arguments are > involved. > > (I was wrong in my earlier message; this can fail in single-threaded > development in consecutive requests. However, the failure is still > subtle, and depending on the details of what you're doing in the view, > may only manifest under certain circumstances. It still falls firmly > in the category of a confusing and non-explicit failure.) > >> Lets be clear here - I don't particularly like *any* of the options on >> the table so far. However, my opinion is that copy on call is the >> option that will provide the least surprising behavior for the most >> common use cases -- having a subset of arguments to __init__ being >> unsafe is less surprising to me that having *all* attributes on self >> either unsafe, or actively prohibited. > > It may be less surprising to you, but it's not at all clear to me that > you are representative of Django users in that :-) It is far more > surprising for me for such a low-level API to be making such odd fine- > grained distinctions about whether I can safely assign mutable or > immutable things to my instance in my __init__ method. > > The issue is not only the frequency of failure, but how explicit/clear > it is. The failure here is so obscure and difficult to track down, it > is likely to generate an outsize support burden. In contrast, raising > an error on assigning to self can be completely explicit; no hours of > painful and confusing debugging necessary. > > Let's also be clear to distinguish "just document that you don't store > state on self" vs "raise an error if you set an attribute on self." > These are proposals with very different characteristics in terms of > likely confusion and support burden.
Agreed. The "just document" approach is a non-starter; the 'error when you set attribute on self' is at least a technically viable option. My problem with the error-based approach is entirely conceptual -- it feels to me like throwing the baby out with the bathwater. I'm having a lot of trouble with the idea that class instances have state in every other Python class instance, and if we introduce an API that physically prohibits instance state that -- no matter how good the technical reasoning -- we're going to: * Cause confusion amongst new users as to why this seemingly obvious thing can't be done * Ignore the legitimate occasions where using state is a useful architectural approach. >> We could even wrap the "no args to __init__" error check in a method >> that enables it to be overridden and silenced in a subclass; that way, >> introducing the potentially un-threadsafe behavior would need to be an > > Again, arguments to __init__ are not the issue. What would have to be > checked is any assignment to self that takes place in __init__. How do > you propose to check that? I don't. You've got me -- in my haste to propose an idea, I hadn't considered assigning state in the constructor. I'm thinking on my feet at the moment, but the only way I can think to resolve this would be to remove the copy() call; effectively making the __call__() a factory that produces a new class instance that shares all the methods of the class-based view, but none of the state created at initialization. However, this is starting to get into the same territory as why the __new__ approach isn't particularly appealing. Yours, Russ Magee %-) -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.