A few days ago, I happened to see a topic in a knowledge planet. Liu said that Python class methods must include self instead of hiding them like other languages, which made me very unhappy. I feel the same way about it. After a group discussion, I learned that Guido had written a special article explaining this issue. This article is not easy to understand, so I took the time to translate it to see what response I could get. If possible, follow up with another article analysis.

————–

Bruce Eckel wrote a blog post proposing to remove “self” from the parameter list of a class method. I shall explain why the proposal cannot be passed. Bruce is the author of “Thinking in Java,” “Thinking in C++,” and a Python developer. His article summarized a discussion that year at Pycon in Brazil, where the main point was that “self” in the parameter is redundant when defining a class method, and that the error message it raises is somewhat misleading.)

Bruce’s proposal

Bruce knew that we needed a way to distinguish references to instance variables from references to other variables, so he suggested “self” as the keyword.

Consider a typical class that has a method such as:

class C:
   def meth(self, arg):
      self.val = arg
      return self.val
Copy the code

Following Bruce’s proposal, this would become:

class C:
   def meth(arg):  # Look ma, no self!
      self.val = arg
      return self.val
Copy the code

This saves 6 characters per method. But I don’t think Bruce is proposing this as a way to cut down on typing.

I think what he really cares about is the time wasted by programmers (probably from other languages) who sometimes don’t seem to need to specify the “self” argument, and who occasionally forget to add it (even though they know full well that habit is a powerful force). Indeed, omitting “self” from the argument list often results in a very ambiguous error message, compared to forgetting to type “self.” before an instance variable or method reference.

Perhaps even worse (as Bruce explained) is the error message you get when you declare a method correctly but call it with the wrong number of arguments. As Bruce gives the following example:

Traceback (most recent call last):
File "classes.py", line 9.in
   obj.m2(1)
TypeError: m2() takes exactly 3 arguments (2 given)
Copy the code

I agree that it’s confusing, but I’d rather fix the error message than fix the language.

Why didn’t Bruce’s proposal work

First, let me make some typical arguments against Bruce’s proposal.

There is a good argument for using explicit “self” in argument lists to enhance the theoretical equivalence of the following two call methods. Suppose “foo” is an instance of “C” :

foo.meth(arg) == C.meth(foo, arg)
Copy the code

To be honest, I don’t understand the point of this example. The following is just my opinion. When you define methods inside a class, several different methods may arise: instance methods, class methods, and static methods. Their roles and behaviors are different, so how do you differentiate between definition and invocation? Python has a convention for defining a method with the first argument: self for instance methods, CLS or some other notation for class methods… All three methods can be called by instances of the class and look exactly the same, as in the example above to the left of the equals sign. In the example above, the first parameter is the instance object, indicating that this is an instance method.

Another argument is to use an explicit “self” in the argument list to insert a function into a class, gaining the ability to dynamically modify a class to create a corresponding class method.

For example, we could create a class that is exactly equivalent to “C” above, as follows:

# Define an empty class:
class C:
   pass

# Define a global function:
def meth(myself, arg):
   myself.val = arg
   return myself.val

# Poke the method into the class:
C.meth = meth
Copy the code

Note that I renamed the “self” parameter to “myself” to emphasize (syntactically) that we are not defining a method here.

After that, the instance of C has an “meth” method that takes one argument and does exactly the same thing. It even works for instances of C that are created before methods are inserted into classes.

I don’t think Bruce was particularly concerned about equivalence. I agree that this is only important in theory. The only exception I can think of is the old idiom for calling super methods. However, this idiom is prone to error (precisely because of the need to explicitly pass “self”), which is why in Python 3000 I recommend using “super()” in all cases.

Bruce might think of a way to make the second equivalent example work — in some cases, this equivalence really matters. I don’t know Bruce spent much time thinking about how to implement his proposal, but I think he is considering an extra parameter called “self” is automatically added to the directly inside the class definition of the thinking of all the methods (I have to say is “directly”, so that those who are nested inside the method of function, can free from this automatic operation). In this way, the first equivalent example remains equivalent.

However, there is one situation that I don’t think Bruce can solve without adding some sort of ESP to the compiler: decorators. I believe this was the final defeat of Bruce’s proposal.

When decorating a method, we don’t know if we should automatically append it with a “self” argument: Decorators can turn a function into a static method (without “self”) or a class method (with an interesting self that points to a class instead of an instance), Or you can do something completely different (implementing decorators for “@classMethod” or “@StaticMethod” in pure Python is cumbersome). Unless you know the purpose of the decorator, there is no other way to determine whether to give the method you are defining an implicit “self” parameter.

I refuse to use special packaged “@classmethod” and “@staticMethod”. I also don’t think it’s a good idea to automatically determine whether a method is a class method, an instance method, or a static method, in addition to self-checking (as someone suggested in the comments to Bruce’s article) : This makes it difficult to determine how a method should be called based solely on the “def” before it.

(For a method, you can simply add a decorator to distinguish which method it is, in the case of the current argument, and easily distinguish the call; However, without arguments, you’re not sure what to call, even though you can use magic automatics to tell which method it is).

In the comments, I’ve seen some very extreme echoes of Bruce’s proposal, but often at the expense of making the rules hard to follow or requiring deeper changes to the language that we find extremely difficult to accept, especially when incorporating Python 3.1. By the way, for 3.1, to reiterate our rule, new features are acceptable only if they remain backward compatible.

One suggestion that seems feasible (to make it backward compatible) is to put classes in

def foo(self, arg):.Copy the code

Change to grammatical sugar like this:

def self.foo(arg):.Copy the code

But I don’t agree that it changes “self” to a reserved word, or that the prefix must be “self.” If this is done, it is easy to do the same for class methods:

@classmethod
def cls.foo(arg):.Copy the code

Okay, I don’t like this any better than the status quo. But compared to the more extreme version proposed by Bruce or in the comments section of his blog, I think this is much better, has the huge advantage of backward compatibility, and doesn’t require much effort to write a PEP with a reference implementation. (I think Bruce would have found flaws in his proposal if he had really put in the effort to try to write a solid PEP or try to implement it.)

I could go on and on, but it was a sunny Sunday morning, and I had other plans… : -)

By Guido Van Rossum on October 26, 2008

English: neopythonic.blogspot.com/2008/10/why…

Guido van Rossum, creator of Python, was a “benevolent dictator for life” until his abdication on July 12, 2018. Currently, he is one of five members of the new top decision-making group who remain active in the community.

Dou Huaxia Cat, born in Guangdong province and graduated from Wuhan University, is now a programmer in Su Piao. She has some geek mentality, some humanistic feelings, some warmth and some attitude. Public id: Python_cat.

The public account “Python Cat”, this serial quality articles, cat philosophy series, Python advanced series, good books recommended series, technical writing, quality English recommended and translation, etc., welcome to pay attention to oh.