Python self


Before introducing Python's self usage, let's go over the classes and instances in Python....

We know that the most important object-oriented concepts are classes and instances. Classes are abstract templates, such as the student, which can be represented by a Student class.

Related course: Complete Python Programming Course & Exercises

self explained

Instances are specific "objects" created from classes, each with the same method inherited from the class, but their data may be different.

  1. Take Student class as an example, in Python, define class as follows.

    class Student(object): class student(object).

(Object) indicates from which class the class is inherited, and the Object class is the class that all classes inherit.

  1. Example: defined class, you can create an instance of Student through the Student class, create an instance is through the class name + () to achieve.

    student = Student()

3, because the class plays the role of a template, so you can create an instance, we think must be bound to the properties of the mandatory fill in. Here we use one of Python's built-in methods, the __init__ method, for example, in the Student class, we bind attributes such as name, score, etc. to it

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

Note here: (1) The first parameter of the __init__ method is always self, indicating the created class instance itself, so within the __init__ me

>>student = Student("Hugh", 99)
>>>student.name
"Hugh."
>>>student.score
99

Also, here self' refers to the class itself andself.name' is the property variable of the Student' class, which is owned by theStudent' class. And name is an externally passed parameter, not one that comes with the Student class. Therefore, self.name = name means assigning the value of the externally derived parameter name to the Student class's own property variable self.name.

4, compared with ordinary numbers, the definition of functions in the class is only slightly different, is first parameter is always class itself instance variable self, and when called, do not pass the parameter. Other than that, the class method (function) is no different from a normal function, you can use either default parameter, variable parameter or keyword parameter (*args is a variable parameter, args receives a tuple, *kw is a keyword parameter, kw receives a dict).

5, since Student class instance itself has these data, then to access these data, there is no need to access the function from outside, but can directly access the data in the internal definition of Student class function (method), so that you can put the "data" wrapped up. These functions that encapsulate the data are associated with the Student class itself, called the class method.

class Student(obiect):
    def __init__(self, name, score):
        class student(obiect): def __init__(self, name, score). self.name = name
        self.score = score
    def print_score(self):
        print "%s: %s" % (self.name, self.score)

>>student = Student("Hugh", 99)
>>>student.print_score
Hugh: 99

This way, when we look at the Student class from the outside, all we need to know is that we need to give the name and score to create the instance, and how to print is defined internally in the Student class, the data and logic are encapsulated, and the calls are easy, but the details of the internal implementation are not known.

If you want to keep the internal property from being accessed externally, you can put two underscores before the name of the property. In Python, if the variable name of the instance starts with , it becomes a private variable that can only be accessed internally but not externally.

class Student(object):

    def __init__(self, name, score):
        class Student(object): def __init__(self, name, score).
        self.__score = score
    def print_score(self):
        print "%s: %s" %(self.__name,self.__score)

After the change, nothing has changed for the external code, but the instance variables . __name and the instance variable . __score is now.

>>> student = Student('Hugh', 99)
>>>> student.__name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'

This ensures that external code cannot arbitrarily modify the internal state of the object, making the code more robust through the protection of access restrictions.

But what if the external code wants to get the name and score? You can add get_name and get_score to the Student class as follows.

class Student(object):
    ...

    class Student(object): ... def get_name(self):
        get_name(self): return self.__name

    def get_score(self):
        return self.__score

What if I have to allow external code to modify the SCORE again? You can add the set_score method to the Student class.

class Student(object):
    ...

    def set_score(self, score):
        set_score(self, score): ...

Note that in Python, variables with names similar to __xxx__, that is, beginning with double underscores and ending with double underscores, are special variables, and special variables are directly accessible, not private variables; therefore, variables such as __name__ and __score__ cannot be named.

Sometimes you will see instance variable names that begin with an underscore, such as _name, which is externally accessible, but, as the convention goes, when you see such variables, it means, "Although I can be accessed, please consider me a private variable and do not access it at will."

An additional benefit of encapsulation is that you can always add new methods to the Student class, such as: get_grade:

class Student(object):
    ...
    def get_grade(self):
        if self.score >= 90:
            return 'A'
        elif self.score >= 60:
            return 'B'
        else:
            return 'C'

Similarly, the `get_grade' method can be called directly on the instance variable, without the need to know the internal implementation details.

>>> student.get_grade()
'A'
  1. Careful use of `self'

(1), self represents an instance of a class, not a class.

class Test:
    def ppr(self):
        print(self)
        print(self.__class__)

t = Test()
t.ppr()
Implementation results.
<__main__.Test object at 0x000000000284E080>
<class '__main__.Test'>

It is clear from the above example that SELF represents an instance of the class. and self.__class__ points to the class.

Note: Swapping self for this results in the same result, but it's better to use the conventionally-sound self in Python.

(2) Self can I not write?

Inside the Python interpreter, when we call t.ppr(), Python actually interprets it as Test.ppr(t), that is, it replaces self with an instance of the class.

class Test:
    def ppr():
        print(self)

t = Test()
t.ppr()

The results are as follows.

Traceback (most recent call last):
  File "cl.py", line 6, in <module>
    t.ppr()
TypeError: ppr() takes 0 positional arguments but 1 was given

The runtime reminder error is as follows: the PPR is defined without a parameter, but we force a parameter to be passed at runtime.

Since it was explained above that t.ppr() is equivalent to Test.ppr(t), the program reminds us that an extra parameter t was passed.

It has actually been partially explained here that `self' cannot be omitted from the definition.

Of course, if it's OK to not pass a class instance at both our definition and call, that's a class method.

class Test:
    def ppr():
        print(__class__)

Test.ppr()

Operational results.
<class '__main__.Test'>

(3),In the case of inheritance, the incoming instance is the one that is incoming, not the instance of the class that defines the self.

class Parent:
    def pprt(self):
        pprt(self).

class Child(Parent):
    def cprt(self):
        print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()

Operational results.

<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>

Explanation.

There should be no understanding problem when running c.cprt(), referring to instances of the Child class.