Re: A proposal (and implementation) to add assignment and LOAD overloading
On Fri, Jun 28, 2019 at 02:44:28AM +1000, Chris Angelico wrote:
If it's ALWAYS called, then it's almost useless. The wrapper object will vanish the moment you attempt to do anything with it, devolving instantly to the result of getself.
I don't understand why it is useless. If the wrapper object is no longer needed, then getself will return the object which is needed, and the wrapper is superfluous and should be garbage collected. If the wrapper object is needed, then getself will return self, and it won't disappear. Are we talking past each other? -- Steven
On Fri, Jun 28, 2019 at 3:55 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Fri, Jun 28, 2019 at 02:44:28AM +1000, Chris Angelico wrote:
If it's ALWAYS called, then it's almost useless. The wrapper object will vanish the moment you attempt to do anything with it, devolving instantly to the result of getself.
I don't understand why it is useless. If the wrapper object is no longer needed, then getself will return the object which is needed, and the wrapper is superfluous and should be garbage collected.
If the wrapper object is needed, then getself will return self, and it won't disappear.
Are we talking past each other?
Without any magic, merely attempting to return the wrapper would cause it to collapse to the underlying object (by calling getself). Therefore, the proposal - to be at all useful - has to have some form of magic to decide whether touching the object gives you the wrapper or calls getself. It's fundamental to the proposal that it be magical. ChrisA
I apologize in advance that this might be slightly off topic from the thread. The idea I want to put forth is probably half baked, but I am wondering if Nate's implementation might be adjusted to incorporate it, and if it might solve a few of the objections. Hopefully someone hasn't already suggested it; I've tried to follow the discussion about this the past couple weeks but there are a lot of messages. The elevator pitch version: add descriptors to modules. Suggested syntax: # inside of my_module a = 1 <-- this does not change # if i specifically want to access a using the of the CURRENT module, i prefix a dot: print(.a) <--- access of a occurs via my_module.__getattr__() when inside my_module # if i specifically want to set a using the (currently not existent) __setattr__() fo the CURRENT module, i do a simliar thing: .a = 2 <-- setting occurs via my_module.__setattr__() when inside my_module In this way, the usage of the module-level attribute getting and setting is entirely VOLUNTARY, and you would expect surprising things to happen when you use the dot. All of the "normal" ways we access variables, which are just names anyway, remain in force: # no changes a = 1 print(a) a = 2 This could be extended to work in other modules: # your_module import my_module my_module.x = 1 <-- magic may occur print(my_module.x) <-- magic may occur Again, this is definitely half baked and I am probably missing something very wrong with it. And I'm sure it has been brought up before. Just throwing it out there as a possible idea related to his discussion. Rick.
On Fri, Jun 28, 2019 at 6:17 AM Ricky Teachey <ricky@teachey.org> wrote:
I apologize in advance that this might be slightly off topic from the thread. The idea I want to put forth is probably half baked, but I am wondering if Nate's implementation might be adjusted to incorporate it, and if it might solve a few of the objections.
Hopefully someone hasn't already suggested it; I've tried to follow the discussion about this the past couple weeks but there are a lot of messages.
The elevator pitch version: add descriptors to modules.
That's mostly available already! https://www.python.org/dev/peps/pep-0562/ # caller.py import mod print(mod.spam) print(mod.eggs) # mod.py def __getattr__(name): return "<synthetic %r>" % name spam = "ham" rosuav@sikorsky:~/tmp$ python3 caller.py ham <synthetic 'eggs'> I don't think there's any __setattr__ support, though, so this isn't quite everything you're looking for. ChrisA
That's mostly available already!
Indeed, and I've been using it! There is also the "clumsy and obscure" method of adding properties to modules discussed in PEP 549 <https://www.python.org/dev/peps/pep-0549/>: import sys, types class _MyModuleType(types.ModuleType): @property def prop(self, instance, owner): ... sys.modules[__name__].__class__ = _MyModuleType This would allow creating a module with managed attribute access AND setting behaviors. I wonder if this kind of approach might help the folks who want to be able to manage variable getting and setting behavior outside of a class namespace--- you could write a module that makes all of its variables behave just the way you want, and import it like so: import managed_variables_module as m m.x = 1 <-- magic print(m.x)<-- magic I'll bow out of this discussion now, as I don't have much to add. This was just a thought.
On Fri, Jun 28, 2019 at 03:59:14AM +1000, Chris Angelico wrote:
Are we talking past each other?
Without any magic, merely attempting to return the wrapper would cause it to collapse to the underlying object (by calling getself).
Yeah, definitely talking past each other. Let's get concrete: class Spam: def __getself__(self): print("I can has side-effects!!!") return self x = Spam() x # Calls __getself__ What are you calling "the wrapper" and "the underlying object"? -- Steven
On Fri, Jun 28, 2019 at 6:36 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Fri, Jun 28, 2019 at 03:59:14AM +1000, Chris Angelico wrote:
Are we talking past each other?
Without any magic, merely attempting to return the wrapper would cause it to collapse to the underlying object (by calling getself).
Yeah, definitely talking past each other.
Let's get concrete:
class Spam: def __getself__(self): print("I can has side-effects!!!") return self
x = Spam() x # Calls __getself__
What are you calling "the wrapper" and "the underlying object"?
It's a distinction that doesn't exist in your example, because you return self. Consider instead: class Spam: def __getself__(self): print("I can has side-effects!!!") return 42 x = Spam() x # Calls __getself__ The wrapper is the instance of Spam, and the underlying object is the integer 42. Which of these will trigger the print call and work with 42, and which will use the Spam object? print(x) # 1 y = x # 2 x.numerator # 3 def f(q): return 7 # 4.1 f(x) # 4.1 def g(q): return q # 5.1 g(x) # 5.2 Quite frankly, I can't be sure. ChrisA
participants (3)
-
Chris Angelico
-
Ricky Teachey
-
Steven D'Aprano