Movatterモバイル変換
[0]ホーム
__module__ (was Re: Deprecate self)
Alex Martellialeaxit at yahoo.com
Fri Apr 20 08:27:37 EDT 2001
"Rainer Deyke" <root at rainerdeyke.com> wrote in messagenews:7aPD6.58066$J%5.19288805 at news2.rdc2.tx.home.com...> "Alex Martelli" <aleaxit at yahoo.com> wrote in message> news:9bn4gu0ugt at news1.newsguy.com...> > "Rainer Deyke" <root at rainerdeyke.com> wrote in message> > news:vQpD6.47756$J%5.15806884 at news2.rdc2.tx.home.com...> > [snip]> > > def f():> > > class C:> > > pass> > > C()> >> > Ok, it's now clearer what you mean, thanks. It doesn't> > STOP somebody sufficiently determined from subclassing> > it, of course:> >> > class OhYeah(f().__class__):> > pass>> Actually I'm not even returning an instance in my example, so even that> isn't possible.True -- you're instancing but not returning it; I had madea "think-o" and read a "return" that wasn't there. If noinstances of the class (as well as the class object itself,method objects, etc) survive the function-execution norescape its confines, you _can_ indeed fully control theuse of the class.> > but it does provide a rather good hint that "being> > subclassed" is not the class's design intention:-).>> > > This is, incidentially, the idiom I had to use extensively to dealwith> > the> > > lack of nested scoping in Python. More generally, you write a classfor> >> > How does a local class help you there in ways nested> > scoping will make obsolete? Sounds interesting.>> def render(draw_fn):> gc = get_gc()> draw_fn(gc)>> def render_text(text):> class Text:> def __init__(self, text):> self.text = text> def draw(gc):> gc.draw_text(self.text)I think you mean "def draw(self, gc):" here, right? (Giventhat this is meant to be current-Python code).> t = Text(text)> render(t.draw)>> In this case I could have used the default argument hack, but that isn't> generally applicable (think *args, **kwargs).True, if you can't 'reserve' any name (need to accept all as **kwargs)you can't use default argument values to bind state, so a local classis a way to get complete generality while a local function will indeedsuffice when scopes nest. Thanks for the example. (I'll even avoidpointing out that, since a bound-method DOES "escape the confines" offunction render_text, inheritance from the local Text class doesbecome _possible_ again -- the render function could be changed toone that defines a class inheriting from draw_fn.im_class -- as thisis so obviously outside of design intent that only a fully paranoidsystem could expend effort to enforce things here:-).> > Nice -- a specifically Pythonic benefit. Of course, it's no> > problem if VariableAccess gets multiply instantiated, so I> > would consider this an example of the pattern "Featherweight"> > (a class whose instances share all state) rather than one of> > the pattern "Singleton" (a class that is protected against> > being multiply instantiated), and I like FW as much as I> > dislike Singleton, so there's still no benefit to the singleton> > design pattern, but that's another issue.>> There is no reason for multiply instantiating 'VariableAccess' because theNo special reason to do so, no special reason to avoid doingso. That is fine with me and doesn't match the descriptionof the "Singleton" design pattern.> defining module provides one instance and every instance other instance is> identical in state and behavior. Whether you call this a "Singleton" or a> "Featherweight" or even "Gorak, destroyer of worlds" is all the same tome.Not to me, nor to most readers, since design patterns' _names_are an important characteristic -- the "primary key" used toretrieve (from memory, a book, etc etc) the various things thatmake up the pattern -- what forces it resolves, how, etc. TheSingleton DP goes to some effort to avoid multiple instantiationand relies on that; I've long thought that expending effort thatis not greater, and in fact is often lesser, to ensure thatmultiple instantiations can occur innocuously (by sharing stateamong potentially-multiple instances), makes for better designpatterns (albeit the catchy "Singleton" name makes it perhapsthe most popular and well-known Gof4 DP). So I'm always on thelookout for situations where the actual forces DO make Singletonpreferable to FeatherWeight -- haven't found any so far.That there exist design situations where a single copy of acertain "state" is desirable, is hardly in question -- that ISa force that comes up again and again. The issue is how tobest resolve it, and the other forces that accompany it invarious use cases.> > > Consider the following hypothetical Python-like language:> > >> > > def f():> > > print 'spam'> > >> > > class C:> > > def f(): # Note lack of 'self'> > > print 'eggs'> > > def g():> > > __instance__.f()> > > __module__.f()> > >> > > I'm not sure I like this myself (the __magic__ names are too long, the> > > result of a 'def' statement depends on context, there's no clear wayto> > > refer to the outer class from a method in an inner class, magically> > > appearing variables have the potential to cause trouble, and the> > > 'C.f(instance_of_C)' conventions seems to be broken), but at leastit's> > > better than the strawman against which you seem to have been arguing.> >> > Actually, I think _this_ is "a strawman proposal" -- one with some> > admitted defects but that at some level realizes design intentions.> > Earlier, I saw complaints but no pointer to resolving them.>> My goal wasn't to change Python, but to discuss a perceived flaw in Python> which later generations of language designers would then be able to avoid> (or alternately to be convinced that the inconsistency is a good idea for> pragmatic reasons).Your "strawman proposal" doesn't seem to show up any inconsistency inPython as it stands. It _does_, to me at least, suggest a possiblelack (specifically that of a __module__ magicnamed attribute in eachmodule object, referring [maybe weakly, or whatever] to the moduleobject itself, to avoid having to import, check sys.modules, etc --assuming for the sake of argument that the need for code in a moduleto refer to the module object IS a frequent enough one to warrant it).> > Thanks for posting it at last. I fully agree with all of your> > criticisms, and furthermore don't see how this will support the> > useful idiom of assigning an existing function to serve as a method,>> Given this:>> def f(x):> do_something_width(x)>> Instead of writing this:>> class C:> do_f = f>> Write this:>> class C:> def do_f():> __module__.f(__instance__) # Where '__module__.' might be optional.Right -- it doesn't support the existing idiom, so you have tocode around it with explicit delegation. Enriching an existingclass-object from outside the class's body seems even more ofa problem -- current "C.do_f=f" becomes...? The "def dependson context" defect that you noticed seems to hurt here.> This is assuming that you want the instance as first argument. There are> times when you don't; see 'VariableAccessor' above.Yes, some people do keep clamoring for "class methods", andthis strawman might support them as it enables methods tobe (e.g.) without arguments. Some would no doubt prefer tohave a simpler "class method" idiom even at the cost oftotally losing the "add a function as a method" one -- andof even deeper black magic than the current type mutation(function to unbound method).> > A somewhat related issue is somehow getting easy access to the> > function object from that function's code -- particularly likely> > to be interesting now that function objects have arbitrary> > attributes. Presumably harder as the __function__ (or> > whatever) would have to be stuck in (the locals...?). Just> > an aside, anyway.>> '__function__' could be treated similarily to default arguments. I don't> see the problem.Placing '__function__' in the local namespace of every singlefunction is a higher cost than placing '__module__' in thenamespace of every module for the very simple reason thatthere are relatively few modules, created pretty rarely, anda LOT of functions, some of which are created more often (ina style using a lot of local functions). The reference circlethat gets created may not be as simple and thus easily handledas " anymodule.__dict__['__module__'] is anymodule " -- itwould presumably be " anyfunc.func_defaults[0] is anyfunc "(but would 0 be appropriate here?) _plus_ something like" anyfunc.func_code.co_varnames[ ??what?? ] == '__function__' "where I guess ??what?? is one more than the actual numberof non-default function parameters. The implementation doesseem more complex to me than the crystal-simplicity of __module__.Maybe the newer mechanisms put in place to support nestedscopes may happen to make this easier -- haven't looked muchat them yet; or maybe there _are_ better places for this thanfunc_defaults anyway. "Presumable harder" (than __module__)seems a fair assessment to me.> > > I'm saying specifically that C++ is right in providing a way toqualify> > > names as global - no more.> >> > OK, I accept that's what you intended to say right from the> > start. Now, "global" in C++ means "global across all sources"> > rather than "specific to this source". Object specific to> > this module would be in the unnamed namespace (since the> > use of 'static' for that is [informally speaking only, I> > believe] deprecated in C++) and thus non-qualifiable; other> > (non-unnamed) namespaces are shared across sources. Are> > you expressing admiration for THIS trait of C++?>> No. I see a certain advantage to C++'s decoupling of file and namespace,> but I am neither talking about it here, nor do I wish it upon Python.OK. Having worked extensively with both languages whichcouple sourcefiles and namespaces/modules (Python, Java,etc) and others that decouple them (C, C++, Fortran) Istrongly prefer the former approach, but if this aspectof the discussion doesn't touch Python then we'd betterdrop it, I guess, as there are so many other subthreadshere that ARE Python-relevant anyway.> > Or do you> > actually wish to keep things Pythonically simple and is> > the C++ reference some sort of red herring? It's starting> > to look that way to me.>> Python is more than complex enough for me.So how would __module__ and __istance__ and __function__and all other such additions REDUCE its complexity thatyou perceive?Alex
More information about the Python-listmailing list
[8]ページ先頭