Sorry for yet another self discussion

I know that "self" parameter have been discussed a lot, but still I didn't find this proposal. If it was instead take my sincere apologies and please forget this mail. The disturbing part of the "self parameter" is the asymmetry of the definition and the call. So I was thinking: why not do define the methods like: "def self.whatevermethod(par1, par2, etc)" instead of "def whatevermethod(self, par1, par2, etc)"? This will allow the call and the definition to be written exactly in the same way, still leaving the "clarity" of the additional input for the function. Moreover this can be made backward compatible (even still without making self a reserved word, to be considered anyway). I've been short by purpose but ready to elaborate if needed. Thank you for the attention. _Stefano

On Thu, May 10, 2018 at 07:58:12PM +0000, stefano wrote:
The disturbing part of the "self parameter" is the asymmetry of the definition and the call.
Why is that disturbing? There is always some asymmetry between *defining* a function and *calling* a function. Function definitions: def function(named parameter list): block Function calls: function(positional arguments) We don't repeat the keyword "def" or the colon in the call, and we obviously don't repeat the body of the block. We typically call the function with either positional arguments, or only a *subset* of the keyword arguments, relying on defaults to fill in the rest. The arguments we provide will often be expressions, sometimes complex expressions, not just simple names. Even if they are simple names, they rarely match the parameter name: Definition: function(spam, eggs, cheese=None, aardvark=True) Call: function((foo + bar) or baz, foobar) So whatever symmetry there is, it isn't much.
"Why not ..." is the wrong question. Adding new features to the language, or new syntax, is not Default Allow ("add the feature, unless there is a compelling reason not to"). There has to be a good, positive reason for adding the feature, not merely a lack of reason not to. What does this feature buy us? Not much. It doesn't add any new expressiveness to the language. It doesn't let the language do anything that couldn't be done before. What it does do is add complexity to the syntax, there now being two ways to specify the first parameter: def self.method(arg) def method(self, arg) both of which need to be supported, which means more complexity to the language, more documentation needed, more for people to learn, more for tutorials to have to cover, more tests needed, etc, and all those costs don't actually gain us any significant advantage for the code we write. And what happens with classmethods and staticmethods, or those people who for whatever reason refuse to use the name "self" for the first parameter? -- Steve

because "self" in this case is a class instance, passed in at method call time. but "whatevermethod" is a class attribute. note the distinction between the class object (shared by all instances) and the instance object. I'm not saying the compiler couldn't make it work, but I am saying that it would confuse the issue -- as it would not be defining an attribute of self, even though it looks like it is. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On 5/10/2018 3:58 PM, stefano wrote:
You are free to use the full signature of the method by calling the method on the class, where it is defined. Self *is* a parameter of the function and therefore *is* part of its signature.
Note that you can make a function defined outside of any class a method of some class by making it an attribute of the class. An intelligent editor like IDLE changes the call signature tip according to the call form. "l.append(" brings up "(object, /)" while "list.append(" brings up "(self, object, /)", along with a note explaining that '/' marks the preceding arguments as positional-only.
This or something like it has been proposed and rejected before.
When you call 'self.method', you are not calling type(self).method. You are instead calling the bound method 'self.method', which has the abbreviated signature. This proposal would create an asymmetry between the function definition and the call of the function. -- Terry Jan Reedy

On Thu, May 10, 2018 at 07:58:12PM +0000, stefano wrote:
The disturbing part of the "self parameter" is the asymmetry of the definition and the call.
Why is that disturbing? There is always some asymmetry between *defining* a function and *calling* a function. Function definitions: def function(named parameter list): block Function calls: function(positional arguments) We don't repeat the keyword "def" or the colon in the call, and we obviously don't repeat the body of the block. We typically call the function with either positional arguments, or only a *subset* of the keyword arguments, relying on defaults to fill in the rest. The arguments we provide will often be expressions, sometimes complex expressions, not just simple names. Even if they are simple names, they rarely match the parameter name: Definition: function(spam, eggs, cheese=None, aardvark=True) Call: function((foo + bar) or baz, foobar) So whatever symmetry there is, it isn't much.
"Why not ..." is the wrong question. Adding new features to the language, or new syntax, is not Default Allow ("add the feature, unless there is a compelling reason not to"). There has to be a good, positive reason for adding the feature, not merely a lack of reason not to. What does this feature buy us? Not much. It doesn't add any new expressiveness to the language. It doesn't let the language do anything that couldn't be done before. What it does do is add complexity to the syntax, there now being two ways to specify the first parameter: def self.method(arg) def method(self, arg) both of which need to be supported, which means more complexity to the language, more documentation needed, more for people to learn, more for tutorials to have to cover, more tests needed, etc, and all those costs don't actually gain us any significant advantage for the code we write. And what happens with classmethods and staticmethods, or those people who for whatever reason refuse to use the name "self" for the first parameter? -- Steve

because "self" in this case is a class instance, passed in at method call time. but "whatevermethod" is a class attribute. note the distinction between the class object (shared by all instances) and the instance object. I'm not saying the compiler couldn't make it work, but I am saying that it would confuse the issue -- as it would not be defining an attribute of self, even though it looks like it is. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On 5/10/2018 3:58 PM, stefano wrote:
You are free to use the full signature of the method by calling the method on the class, where it is defined. Self *is* a parameter of the function and therefore *is* part of its signature.
Note that you can make a function defined outside of any class a method of some class by making it an attribute of the class. An intelligent editor like IDLE changes the call signature tip according to the call form. "l.append(" brings up "(object, /)" while "list.append(" brings up "(self, object, /)", along with a note explaining that '/' marks the preceding arguments as positional-only.
This or something like it has been proposed and rejected before.
When you call 'self.method', you are not calling type(self).method. You are instead calling the bound method 'self.method', which has the abbreviated signature. This proposal would create an asymmetry between the function definition and the call of the function. -- Terry Jan Reedy
participants (4)
-
Chris Barker
-
stefano
-
Steven D'Aprano
-
Terry Reedy