I created a discussion topic located here
https://discuss.python.org/t/a-proposal-and-implementation-to-add-assignment-and-load-overloading/1905

On Tue, Jun 25, 2019 at 6:41 PM nate lust <natel...@linux.com> wrote:

> 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*
>>
>

-- 
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/LSCLXMT46HEAFUSDAQ6HAOGCBV7UEHLM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to