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

Reply via email to