In article <4e5ed670$0$29981$c3e8da3$54964...@news.astraweb.com> Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: >Er, yes, just like I suggested in my opening paragraph, and as I answered >following the bit you marked as snipped :)
Oops, so you did (went back and re-read it). Must have gotten interrupted and lost track. :-) >> [A different hack would] requires a bit of implicit >> sneakiness in the compiler: an instance method magically creates >> a local variable named "self" that binds to the invisible first >> parameter, and a class method magically creates a local variable >> named "cls" that binds to the invisible first parameter, and so >> on. >It would need more than "a bit", because methods are just wrappers >around functions. Well, depends on how the hack would be done. :-) For instance, the @decorator might turn on something that "undoes" or "replaces" the "self" parameter. That is, with ordinary class functions and methods: class HackyNotQuitePythonVersion: def ordinary(arg): self.arg = arg would compile to (approximately): class PythonVersion: def __mrap(self, *args, **kwargs): def ordinary(arg): self.arg = arg ordinary(*args, **kwargs) ordinary = __mrap (add the usual other manipulations to suit here, i.e., all the stuff for making introspection work right, i.e., @functools.wraps). @staticmethod would suppress the wrapper entirely, while @classmethod would change it to one that binds the "cls" argument. (Any function without some appropriate @whatever gets the Method Wrapper __mrap. @staticmethod tells the class builder not to add any wrapper, and @classmethod tells it to add the Class Wrapper __crap. [The name tells you what I think of the above code. :-) ]) (Note subtle ground for bugs here: if you then actually define a "self" parameter, it shadows the outer-scope one from the wrapper. So while I am not even proposing that anyone should do this in the first place, it has more downsides than mere implementation complexity.) >Another way would be for the compiler to perform darkest black magic to >determine whether the function was being called from inside a method or >not. That would be complicated and fragile. Yes, even worse than my outlined implementation above, I think. >classmethod and staticmethod are functions, not declarations. They are decorator functions, but to someone *reading the code* they are also "declarations" of sort. This is all I meant: they tell the (human) reader/programmer which "secret arguments" to expect. >You can't assume that @classmethod is the only way to get a >class method: the metaclass could do it, or you could inject >one in from the outside. Yes, but that would all still work, as in this not-quite-Python (worsened-Python) language, whoever writes those metaclasses and other decorators would continue to do whatever icky stuff was required (e.g., __mrap and __crap above). It would mean yet more things for people to know about, but then, metaclasses and decorators *always* mean that: @hmm def spam(): return magic Is "magic" something supplied by the decorator? You have to look at the decorator to find out, as the rather horrid example I have attached shows. (Note: I am doing all this is python 2.x on the laptop. Using global, in @hmm, is evil, but it works. I did not bother trying to write a metaclass that inserts __mrap, etc., but I believe it can be done.) >Python classes have a lot of dynamism made possible by the fact that methods >are just wrappers around functions with an explicitly declared "self". That >dynamism is rarely used, but not *that* rarely, and is very useful when >used. Implicit self would likely negate all that. I do not believe it would *negate* it, just *complicate* it. But that is not a good thing either. :-) ----- horrible example / test code below import functools def hmm(func): @functools.wraps(func) def wrapper(*args, **kwargs): global magic, rlevel try: save = magic, rlevel restore = True rlevel += 1 except NameError: restore = False rlevel = 1 magic = func.__name__ + " and eggs" ret = func(*args, **kwargs) if restore: magic, rlevel = save else: del magic, rlevel return ret return wrapper @hmm def ham(): if rlevel < 2: print spam() return magic @hmm def spam(): return magic print ham() try: print magic except NameError: print 'name "magic" is not available here, as desired' try: print rlevel except NameError: print 'name "rlevel" is not available here, as desired' class X(object): def __mrap(self, *args, **kwargs): def xset(arg): self.arg = arg xset(*args, **kwargs) xset = __mrap def __mrap(self, *args, **kwargs): def show(): print self.arg show(*args, **kwargs) show = __mrap x = X() x.xset('value') x.show() -- In-Real-Life: Chris Torek, Wind River Systems Intel require I note that my opinions are not those of WRS or Intel Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603 email: gmail (figure it out) http://web.torek.net/torek/index.html
-- http://mail.python.org/mailman/listinfo/python-list