The self& descriptor in Python __set__ and __get__& a simple summary __python

Source: Internet
Author: User
1. Summary of self usage in Python
Class Student (object):
    def __init__ (self, Name, score):
        self.name = name
        Self.score = Score
The first parameter of the __init__ method is always self, which means that the class instance itself is created, so that within the __init__ method, you can bind various properties to self, because self points to the instance itself created. With the __init__ method, when you create an instance, you cannot pass in an empty argument, and you must pass in the Initmethod, but self does not need to pass, and the Python interpreter will pass the instance variable in itself. Defining a function in a class is a little different than a normal number, that is, the first argument is always the class's own instance variable self, and when invoked, it is not passed. In addition, the class method (function) and the normal function are no different, you can use the default parameters, variable parameters or keyword parameters (*args is a variable parameter, args receives a tuple,**kw is the keyword parameter, kw receives a dict)If you want internal properties to not be accessed externally, you can add a two underline to the name of the property, in Python, the instance's variable name, if it starts, becomes a private variable (private), accessible only internally, and not externally. It should be noted that in Python, the variable name is similar XXX, that is, the beginning of a double underline, and the end of a double underline, is a special variable, special variables can be directly accessed, not private variables, so, you can not use __name__, __score__ such a variable name sometimes, you will see an underscore beginning with an instance variable name, For example _name, such an instance variable outside is accessible, but, according to the conventions, when you see such a variable, meaning, "although I can be accessed, but, please treat me as a private variable, do not randomly access."

Here are some detailed uses of self:

(1) Self represents an instance of a class, not a class

in [[]: Class Test:
    ...:     def PPR (self):
    ...:         print (self) ...
    :         print (self.__class__)
    ..: in  

[m]: t = Test () in

[]: T.PPR ()
<__main__. Test instance at 0x000000000d3d4e88>
__main__. Test

Self represents an instance of a class. and self.__class__ points to classes.
Note: Replacing self with this will result in the same, but it is best to use the conventional self in python.

(2) Self can not write?
Inside the Python interpreter, when we call T.PPR (), Python is actually interpreted as TEST.PPR (t), which replaces self with an instance of the class.

In []: Class Test:
    ...:     def PPR ():
    ..:         print (self)
    ...: in [?     

]: T=test () in

[ ]: T.PPR ()
Traceback (most recent call last):

  File "<ipython-input-24-178e9dc94925>", line 1, in < Module>
    t.ppr ()

typeerror:ppr () takes no arguments (1 given)

This is in fact part of the explanation that self can not be omitted when defining.

Of course, if our definitions and calls do not pass class instances is OK, this is the class method.

>>> class Test:
    def PPR ():
        print (__class__)


>>> test.ppr ()
<class ' __main__. Test ' >

But here's the note: for the Python 2.7 version it will be an error, you must first create the object.

In [to]: Class Test:
    ...:     def PPR ():
    ...:         print (' I am here ')
    ...: in         

[i]: test.ppr ()
Traceback (most recent):

  File "<ipython-input-32-f7a5b2f2ccd9>", line 1, in <module>
    TEST.PPR ()

Typeerror:unbound method PPR () must is called with Test instance as-a-argument (got nothing instead)

(3) In the case of inheritance, which instance is passed in, which is the passed-in instance, not the instance of the class that defines self

>>> class Parent:
    def pprt (self):p rint (self)


>>> class Parent:
    def pprt (self):
        Print (self)


>>> class Child (Parent):
    def cprt (self):
        print (self)


>>> c=child ()
>>> c.cprt ()
<__main__. Child object at 0x00000244b8769860>
>>> c.pprt ()
<__main__. Child object at 0x00000244b8769860>
>>> p = Parent ()
>>> p.pprt ()
<__main__. Parent Object at 0x00000244b8769a58>

(4) In a descriptor class, self refers to an instance of a descriptor class

Class DESC2:
    def __get__ (self, INS, CLS):
        print (' Self in Desc:%s '% self)
        print (self, ins, CLS)

C Lass Test2:
    x = DESC2 () # and the property is a descriptor property, an instance of the Desc class
    def prt (self):
        print (' Self in Test:%s '% self)

t2 = T Est2 ()
t2.prt ()
t2.x # Here is the calling class attribute
test2.x # Notice the difference from the line above

Run Result:

Self in Test: <__main__. Test2 object at 0x00000239ce269128>
self in Desc: <__main__. DESC2 object at 0x00000239ce2690b8> 
<__main__. DESC2 object at 0x00000239ce2690b8> <__main__. Test2 object at 0x00000239ce269128> <class ' __main__. Test2 ' >
self in Desc: <__main__. DESC2 object at 0x00000239ce2690b8> 
<__main__. DESC2 object at 0x00000239ce2690b8> None <class ' __main__. Test2 ' >

Because in many cases the descriptor class still needs to know who is calling the descriptor, there is a second parameter ins in the Descriptor class that represents the class instance that invoked it, so t.x can see that the second item in the run result in the third row is <__main__. Test2 object at 0x00000239ce269128> 2. Descriptors __set__ and __get__ usage

can refer to the following: https://blog.csdn.net/lilong117194/article/details/80111803

The questions above should be __get__ (self, INS, CLS), and here's a summary:
First of all, there are several methods in Python: Object method, static method, class method, and so on, the ownership is obj, CLS, CLS
It can be seen from their arguments, static methods are decorated with @staticmethod and can be invoked through instance objects of a class or class.

Class A (object):
      def foo1 (self):
          print ("Hello", self)
      @staticmethod
      def foo2 ():
          print ("Hello")
      @classmethod
      def Foo3 (CLS):
          print ("Hello", CLS)  # CLS is the Class A itself 
a = a ()
a.foo1 ()

a.foo1 ( A)   #这里传入实例a, the Self A.foo2 () equivalent to the normal method    #这里, because the static method has no parameters, it can not pass the

A.foo3 ()    #这里, because it is a class method, Its first argument is the class itself.

print (a)     #可以看到, enter A directly, and return the same information as the above call

Results:

Hello <__main__. A object at 0x0000016d1774b860>
Hello <__main__. A object at 0x0000016d1774b860>
Hello
hello <class ' __main__. A ' >
<class ' __main__. A ' >

In Python, the object's method can also be considered a property, so the following attribute contains the method.
Look at an example:

Class T (object):
    name = ' name '
    def hello (self):
        print ("Hello")
t = t ()
print (' dir (t): ', dir (t)) Print ('
t.__class__: ', t.__class__)
print (' t.__dict__: ', t.__dict__) 
print (' t.__dict__: ', Dict (t.__ dict__)) # t.__dict__ does not directly return Dict object, which is converted to dictionary

print (' T.name: ', t.name) print ('
t.name: ', t.name)
print (' t.dict[' name ']: ', t.__dict__[' name ')

print (' T.hello: ', T.hello) # is a unbound method
print ("t.__dict__[" Hello ']: ', t.__dict__[' hello '] # is a function
print (' T.hello: ', T.hello) # is a bound method

Run Result:

dir (t): [' __class__ ', ' __delattr__ ', ' __dict__ ', ' __dir__ ', ' __doc__ ', ' __eq__ ', ' __format__ ' ', ' __ge__ ', ' __getattribute__ ', ' __gt__ ', ' __hash__ ', ' __init__ ', ' __le__ ', ' __lt__ ', ' __module__ ', ' __ne__ ', ' __new__ ' , ' __reduce__ ', ' __reduce_ex__ ', ' __repr__ ', ' __setattr__ ', ' __sizeof__ ', ' __str__ ', ' __subclasshook__ ', ' __weakref__ ' , ' Hello ', ' name '] t.__class__: <class ' __main__. T ' > t.__dict__: {} t.__dict__: {' name ': ' Name ', ' __doc__ ': None, ' __weakref__ ': <attribute ' __weakref__ ' ' ' t ' obje Cts>, ' __module__ ': ' __main__ ', ' hello ': <function T.hello at 0x000002bb9572b400>, ' __dict__ ': <attribute ' _ _dict__ ' ' T ' objects>} t.name:name t.name:name t.dict[' name ': Name T.hello: <function T.hello at 0x000002bb957 2b400> t.__dict__[' Hello ': <function t.hello at 0x000002bb9572b400> T.hello: <bound method T.hello of <__ main__. T object at 0x000002bb97b49860>> 

Note: Some built-in types, such as list and string, do not have dict attributes, and there is no way to attach custom attributes to them t.__dict__: {} : So far t.dict is an empty dictionary because we have not customized any attributes on T, and its valid properties Hello and name are all obtained from T.

T.name Lookup process: First, Python determines whether the Name property is an automatically generated property, and if it is an automatically generated attribute, it is found in a special way, and of course, the name here is not an automatically generated attribute, but we define it ourselves. Python then went to the dict of T to look for it. Still can't find it. Then Python finds the class T that T belongs to, searches for t.dict, and returns the value of name: String ' name '. If not found in T.dict, Python continues to look in the dict of T's parent class (if T has a parent).

T.hello: Methods exist in the dict of the class in the form of functions about unbound and bound: The method is to be invoked from the instance, if accessed from the class, such as T.hello,hello does not have a connection with any instance, that is, unbound (unbound) To any instance, so it's a unbound, the way the T.hello is accessed, hello and T are connected, so it's bound.

Let's look at one more example:

Class Descriptor (object):
    def __get__ (self, obj, Type=none): Return
            ' get ', self, obj, type
    def __set__ (self , obj, val):
        print (' Set ', self, obj, Val)
    def __delete__ (self, obj):
        print (' delete ', self, obj)


class T ( Object):
    # D is the class attribute of T, and as an instance of descriptor, it has methods such as GET, which is a descriptor
    D = descriptor () 


t = t () # T is a class, T is an instance of it, D is a descriptor property of T
(' T.D: ', T.D) # T.D, the actual return is d.__get__ (T, T)
print (' T.D: ', T.D) # T.D, the actual return is d.__get__ ( None, T), so the position of obj is none
t.d = ' Hello ' # sets the value on the instance on the descriptor, which is output by the print statement in the __set__ method.
print (' T.D: ', T.D) # visible, called Python called the __set__ method, and did not change the T.D value
T.D = ' Hello ' # did not call the __set__ method
print (' T.D: ', T.D)
# The value of T.D is also changed, which can be understood, according to the attribute lookup policy we mentioned above, T.D is obtained from the t.__dict__ The value of dict__[' d ' is ' hello ', t.d of course also ' Hello '
print (' T.D: ', T.D)

Run Result:

T.D: (' Get ', <__main__. Descriptor object at 0x000001f403df9860>, <__main__. T object at 0x000001f403e5b6d8>, <class ' __main__. T ' >)
 t.d: (' Get ', <__main__. Descriptor object at 0x000001f403df9860>, None, <class ' __main__. T ' >)
set <__main__. Descriptor object at 0x000001f403df9860> <__main__. T object at 0x000001f403e5b6d8> Hello
 t.d: (' Get ', <__main__. Descriptor object at 0x000001f403df9860>, <__main__. T object at 0x000001f403e5b6d8>, <class ' __main__. T ' >)
 t.d:hello
 T.d:hello

Here are a few things to say: Self, of course, is an instance of the current descriptor class. The obj value owns the object of the property. This should not be difficult to understand, as has been said before, descriptor is a slightly special attribute of the object, where obj is the object that owns it. Note that if you are accessing the descriptor directly with the class (descriptor is a property, accessing the descriptor directly using the Class), obj is None, and the type is the class itself. When a property is read, such as T.D, the result of the D.get (None, T) is returned, and T.D returns the result of the D.get (T, T). When setting a property, T.D = value, which actually calls D.set (T, value) T.D = value, which is the true assignment, and the T.D value becomes value. Deleting a property is similar to setting the property.

Data Descriptor and Non-data descriptor:
Like the above D, also has the get and set methods, such descriptor is called the data descriptor, if only get method, is called Non-data descriptor. It is easy to think that because the Non-data descriptor does not have a set method, the value is directly assigned when the property is assigned through an instance.

Attribute Lookup policy :
1. If attr is an automatically generated property of Python, find it. (The priority is very high.) )
2. Find Obj.class.dict, if attr exists and is a data descriptor, returns the result of the Get method of data descriptor if it does not continue looking for data in the Obj.class parent class and Ancestor class Descriptor
3. Find in Obj.dict, this step is divided into two cases, the first case is obj is a common instance, find it directly back, can not find the next step. The second case is that obj is a class that, in turn, looks in the dict of obj and its parent class, ancestor class, and returns attr directly if a descriptor is found to return the result of the descriptor get method. If it is not found, proceed to the next step.
4. Find in Obj.class.dict, if found a descriptor (insert: The descriptor here must be non-data descriptor, if it is data descriptor, the second step to find it) The result of the descriptor get method. If a normal property is found, the property value is returned directly. If it is not found, proceed to the next step.
5. Unfortunately, Python was finally overwhelmed. In this step, it raise attributeerror

Here has been almost, but still some are not understood very thoroughly, later study slowly.

Reference: https://blog.csdn.net/u014015972/article/details/51168268

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.