I am happy to move this discussion to where ever is appropriate. I won't get to it in the next few hours (bed time for my kid) so if you would like feel free to move discussion there, and I guess I can watch this email thread for if you do. Otherwise I will do it when I am free. Nate
On Tue, Jun 25, 2019, 6:36 PM Juancarlo Añez <apal...@gmail.com> wrote: > Nate, > > I find this mightily interesting! I think it's worth discussing at length. > > Is there any chance you'll want to move the discussion to the richer > context here? https://discuss.python.org/c/ideas > > Regards, > > On Tue, Jun 25, 2019 at 5:00 PM nate lust <natel...@linux.com> wrote: > >> This message is related to two previous threads, but was a sufficiently >> evolved to warrant a new topic. >> >> I am proposing that two new magic methods be added to python that will >> control assignment and loading of class >> instances. This means that if an instance is bound to a variable name, >> any attempts to rebind that name will >> result in a call to the __setself__ (name negotiable) of the instance >> already bound to that name. Likewise >> when a class instance bound to a name is loaded by the interpreter, if >> present, the __getself__ method of that >> instance will be called and its result will be returned instead. I have >> been internally calling these cloaking >> variables as they "cloak" the underlying instance, parallelling the idea >> of shadowing. Feel free to suggest >> better names. >> >> >> On first read, that may be surprising, but it extends a behavior pattern >> that already exists for things like >> properties (and generically descriptors) to object instances themselves. >> Similar caveats and behaviors will >> apply here as well. >> >> A working implementation built against python 3.7 can be found here: >> https://github.com/natelust/cpython/tree/cloakingVars. This is not pull >> ready quality code, but the diffs may >> be interesting to read. >> >> An example for what is possible for this new behavior are instance level >> properties as seen in the demo at the >> end of this message. >> >> These changes have minimal impact on the runtime of existing code, and >> require no modifications to existing >> syntax other than the use of the names __setself__ and __getself__. >> >> A more detailed write-up with more examples can be found at >> https://github.com/natelust/CloakingVarWriteup/blob/master/writeup.md, >> with the example executable demo here: >> https://github.com/natelust/CloakingVarWriteup/blob/master/examples.py >> >> The demos include: >> * Variables which keep track of their assignment history, with ability to >> rollback (possibly useful with try >> except blocks) >> * Variables which write out their value to disk when assigned to >> * An implementation of context variables using only this new framework >> (does not implement tokens, but could >> be added) >> * const variables that can be used to protect module level 'constants' >> * Instance properties (reproduced below) that allow dynamically adding >> properties >> * An implementation of templated expression, to defer the addition of >> many arrays to a single for loop, >> saving possibly expensive python iterations. >> >> I am sure the community can come up with many more interesting ideas. >> >> class InstanceProperty: >> >> def __init__(self, wrapped, getter, setter=None): >> self.wrapped = wrapped >> self.getter = getter >> self.setter = setter >> >> def __getself__(self): >> return self.getter(self.wrapped) >> >> def __setself__(self, value): >> if self.setter: >> return self.setter(self.wrapped, value) >> >> >> class MachineState: >> def __init__(self): >> self._fields = {} >> >> def add_input(self, name, start): >> def getter(slf): >> return slf._fields[name] >> >> def setter(slf, value): >> ''' >> the state of a machine part can only be above zero or below >> 100 >> ''' >> if value < 0: >> value = 0 >> if value > 100: >> value = 100 >> slf._fields[name] = value >> setter(self, start) >> inst_prop = InstanceProperty(self, getter, setter) # noqa: F841 >> # Need to directly assign the instance property, or decloak it. >> setattr(self, name, getcloaked('inst_prop')) >> >> >> machine = MachineState() >> >> for letter, start in zip(['a', 'b', 'c'], [-1, 0, 1]): >> machine.add_input(letter, start) >> >> print(f"machine.a is {machine.a}") >> print(f"machine.b is {machine.b}") >> print(f"machine.c is {machine.c}") >> >> # Assign a value that is too high >> machine.c = 200 >> >> print(f"machine.c is {machine.c}") >> # Omited from this proposal but present in the linked documentation are >> # tools for getting the underlying variables, and or rebinding them. >> >> On Fri, Jun 21, 2019 at 9:34 PM nate lust <natel...@linux.com> wrote: >> >>> It probably doesn't, this was just something I typed up on the fly, so >>> is unlikely the end result would be what you see above if it was actually >>> implemented. >>> >>> The only way around that that I can think of now would be if there was >>> two functions, an impl_dictget that actually did the lookup that type could >>> use (and possibly getattr and the like) which would be called in the normal >>> dict get which would just return if the type did not define __getself__ and >>> would call it and return the result if it did. >>> >>> This is not at all dissimilar to how dict setting works now >>> >>> On Fri, Jun 21, 2019, 9:27 PM Chris Angelico <ros...@gmail.com> wrote: >>> >>>> On Sat, Jun 22, 2019 at 11:19 AM nate lust <natel...@linux.com> wrote: >>>> > Typing this out though does make me think of an interesting idea. If >>>> there was something like __getself__ in addition to __setself__, you could >>>> implement things like MyInt. __getself__ would look something like: >>>> > >>>> > class MyInt: >>>> > def __init__(self, value): >>>> > self.value = value >>>> > def __getself__(self): >>>> > return self.value >>>> > def __setself__(self, value): >>>> > raise ValueError("Cant set MyInt") >>>> > x = MyInt(2) >>>> > print(x) -> 2 >>>> > type(x) -> MyInt >>>> > >>>> > Now I have not really thought through how this would work, if it >>>> could work... >>>> >>>> How does print know to call getself, but type know not to? >>>> >>>> ChrisA >>>> _______________________________________________ >>>> Python-ideas mailing list -- python-ideas@python.org >>>> To unsubscribe send an email to python-ideas-le...@python.org >>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >>>> Message archived at >>>> https://mail.python.org/archives/list/python-ideas@python.org/message/3734V62OHMJN3736PKWQ7IZ533TPM23J/ >>>> Code of Conduct: http://python.org/psf/codeofconduct/ >>>> >>> >> >> -- >> Nate Lust, PhD. >> Astrophysics Dept. >> Princeton University >> _______________________________________________ >> Python-ideas mailing list -- python-ideas@python.org >> To unsubscribe send an email to python-ideas-le...@python.org >> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >> Message archived at >> https://mail.python.org/archives/list/python-ideas@python.org/message/TMU3MJCDVNAHMJQAJUBIHRJXXLYMWSRH/ >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > > > -- > Juancarlo *Añez* >
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/IS5NJ7U5IXRPXOVVGQPO652X3Z7CF2QM/ Code of Conduct: http://python.org/psf/codeofconduct/