zoukankan      html  css  js  c++  java
  • self参数

    self参数

    self指的是实例Instance本身,在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self,

    也就是说,类中的方法的第一个参数一定要是self,而且不能省略。关于self有三点是很重要的:

    self指的是实例本身,而不是类
    self可以用this替代,但是不要这么去写
    类的方法中的self不可以省略
    class Person():
    def eat(self):
    print(self)
    Alex = Person()
    Alex.eat()
    print(Person)

    __ init__ ()方法

    在python中创建类后,通常会创建一个 __ init__ ()方法,这个方法会在创建类的实例的时候自动执行

    __ init__ ()方法必须包含一个self参数,而且要是第一个参数

    
    
    class Person():
    def __init__(self):
    print("是一个人")
    #self.name = name
    def eat(self):
    print("吃饭")
    Alex = Person()

    是一个人
    __ init__ ()方法就已经自动执行了,但是如果不是 __ init__ ()方法,比如说eat()方法,那肯定就只有调用才执行

    再比如说下面的代码,如果 __ init__ ()方法中还需要传入另一个参数name,但是
    我们在创建Alex的实例的时候没有传入name,那么程序就会报错,

    class Person():
    def __init__(self,name):
    print("是一个人")
    self.name = name
    def eat(self):
    print("吃饭")
    Alex = Person()

     我们其实就比较清晰的知道什么东西需要在__ init__ ()方法中定义了,就是希望有一些操作是在创建实例的时候就有,

    我们写神经网络的代码的时候,一些网络结构的设置,也最好放在__ init__ ()方法中。

    super(Net, self).init()

    python中的super(Net, self).init()是指首先找到Net的父类(比如是类NNet),然后把类Net的对象self转换为类NNet的对象,然后“被转换”的类NNet对象调用自己的init函数,

    其实简单理解就是子类把父类的__init__()放到自己的__init__()当中,这样子类就有了父类的__init__()的那些东西。

    Net类继承nn.Module,super(Net, self).init()就是对继承自父类nn.Module的属性进行初始化。

    而且是用nn.Module的初始化方法来初始化继承的属性。

    class Net(nn.Module):
    
        def __init__(self):
            super(Net, self).__init__()
            # 输入图像channel:1;输出channel:6;5x5卷积核
            self.conv1 = nn.Conv2d(1, 6, 5)

    也就是说,子类继承了父类的所有属性和方法,父类属性自然会用父类方法来进行初始化。
    当然,如果初始化的逻辑与父类的不同,不使用父类的方法,自己重新初始化也是可以的。比如:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    class Person(object):
        def __init__(self,name,gender,age):
            self.name = name
            self.gender = gender
            self.age = age
     
    class Student(Person):
        def __init__(self,name,gender,age,school,score):
            #super(Student,self).__init__(name,gender,age)
            self.name = name.upper()  
            self.gender = gender.upper()
            self.school = school
            self.score = score
     
    s = Student('Alice','female',18,'Middle school',87)
    print (s.school)
    print (s.name)
    print (s.age) #报错,因为没有初始化
    Middle school
    ALICE

    class Person(object):#父类
        def __init__(self, name, gender, age):
            self.name = name
            self.gender = gender
            self.age = age
    class Student(Person):
        def __init__(self, name, gender, age, school, score):
            super(Student,self).__init__(name,gender,age)
            # self.name = name.upper()
            # self.gender = gender.upper()
            self.school = school
            self.score = score
    s = Student('Alice', 'female', 18, 'Middle school', 87)
    print(s.school)
    print(s.name)
    Middle school
    Alice

    class Person(object):
        def __init__(self, name, gender, age):
            self.name = name
            self.gender = gender
            self.age = age +2
    
    
    class Student(Person):
        def __init__(self, name, gender, age, school, score):
            super(Student,self).__init__(name,gender,age)
            # self.name = name.upper()
            # self.gender = gender.upper()
            self.school = school
            self.score = score
    
    
    s = Student('Alice', 'female', 18, 'Middle school', 87)
    print (s.school)
    print (s.age)
    Middle school
    20 #(18+2)

    class Person(object):
        def __init__(self, name, gender, age):
            self.name = name
            self.gender = gender
            self.age = age +2
    
    
    class Student(Person):
        def __init__(self, name, gender, age, school, score):
            super(Student,self).__init__(name,gender,age)
            self.name = name.upper()#继承后仍可以修改
            # self.gender = gender.upper()
            self.school = school
            self.score = score
    
    
    s = Student('Alice', 'female', 18, 'Middle school', 87)
    print (s.name)
    print (s.age)

    ALICE

    20

    def __init__(self, name, gender, age, school, score):
    super(Student,self).__init__(name,age,gender)#报错,顺序要匹配


    def __init__(self, name, gender, age, school, score):
    super(Student,self).__init__(name,gender)#报错,不可缺少父类属性


    下面解释Python的super()函数

    1.python子类调用父类成员有2种方法,分别是普通方法和super方法

    假设Base是基类

    class Base(object):
      def __init__(self):
        print “Base init”

    则普通方法如下

    class Leaf(Base):
         def __init__(self):
             Base.__init__(self)
            print “Leaf init”

    super方法如下

    class Leaf(Base):
         def __init__(self):
             super(Leaf, self).__init__()
             print “Leaf init”

    两种方法的效果一样

    我们就遇到了一个难题:

    class Base(object):
           def __init__(self):
                  print “Base init”
     
    class Medium1(Base):
           def __init__(self):
                  Base.__init__(self)
                  print “Medium1 init”
     
    class Medium2(Base):
           def __init__(self):
                  Base.__init__(self)
                  print “Medium2 init”
     
    class Leaf(Medium1, Medium2):
           def __init__(self):
                  Medium1.__init__(self)
                  Medium2.__init__(self)
                  print “Leaf init”    
    
    leaf  =Leaf()

     Base被初始化了两次!这是由于Medium1和Medium2各自调用了Base的初始化函数导致的。

    解决方法:

    Python使用的是super重写一下,看一下输出结果

    class Base(object):
           def __init__(self):
                  print “Base init”
     
    class Medium1(Base):
           def __init__(self):
                  super(Medium1, self).__init__()
                  print “Medium1 init”
     
    class Medium2(Base):
           def __init__(self):
                  super(Medium2, self).__init__()
                  print “Medium2 init”
     
    class Leaf(Medium1, Medium2):
           def __init__(self):
                  super(Leaf, self).__init__()
                  print “Leaf init”        
    leaf  =Leaf()

    Base init

    Medium2 init

    Medium1 init

    Leaf init

    super的内核:mro

    要理解super的原理,就要先了解mro。mro是method resolution order的缩写,表示了类继承体系中的成员解析顺序

    在python中,每个类都有一个mro的类方法。我们来看一下钻石继承中,Leaf类的mro是什么样子的:

    >>> Leaf.mro()

    [<class '__main__.Leaf'>, <class '__main__.Medium1'>, <class '__main__.Medium2'>, <class '__main__.Base'>, <type 'object'>]

    可以看到mro方法返回的是一个祖先类的列表。Leaf的每个祖先都在其中出现一次,这也是super在父类中查找成员的顺序。 

    通过mro,python巧妙地将多继承的图结构,转变为list的顺序结构。super在继承体系中向上的查找过程,变成了在mro中向右的线性查找过程,任何类都只会被处理一次。

    通过这个方法,python解决了多继承中的2大难题:

    1. 查找顺序问题。从Leaf的mro顺序可以看出,如果Leaf类通过super来访问父类成员,那么Medium1的成员会在Medium2之前被首先访问到。

        如果Medium1和Medium2都没有找到,最后再到Base中查找。

    2. 钻石继承的多次初始化问题。在mro的list中,Base类只出现了一次。事实上任何类都只会在mro list中出现一次

        这就确保了super向上调用的过程中,任何祖先类的方法都只会被执行一次。

    super的具体用法

    (1) super(type, obj)

    class Leaf(Medium1, Medium2):
           def __init__(self):
                  super(Leaf, self).__init__()
                  print “Leaf init”

    super(Leaf, self).__init__()的意思是说:

    1. 获取self所属类的mro, 也就是[Leaf, Medium1, Medium2, Base]
    2. 从mro中Leaf右边的一个类开始,依次寻找__init__函数。这里是从Medium1开始寻找
    3. 一旦找到,就把找到的__init__函数绑定到self对象,并返回

    从这个执行流程可以看到,如果我们不想调用Medium1的__init__,而想要调用Medium2的__init__,那么super应该写成:super(Medium1, self)__init__() 

    (2) super(type, type2)

    class Leaf(Medium1, Medium2):
           def __new__(cls):
                  obj = super(Leaf, cls).__new__(cls)
                  print “Leaf new”
                  return obj

    super(Leaf, cls).__new__(cls)的意思是说:

    1. 获取cls这个类的mro,这里也是[Leaf, Medium1, Medium2, Base]
    2. 从mro中Leaf右边的一个类开始,依次寻找__new__函数
    3. 一旦找到,就返回“非绑定”的__new__函数

    由于返回的是非绑定的函数对象,因此调用时不能省略函数的第一个参数。这也是这里调用__new__时,需要传入参数cls的原因

    同样的,如果我们想从某个mro的某个位置开始查找,只需要修改super的第一个参数就行

  • 相关阅读:
    Joomla 3.9.13 二次注入分析(CVE-2019-19846)
    Wordpress未授权查看私密内容漏洞 分析(CVE-2019-17671)
    Thinkphp 5.1.24 parseKey缺陷导致聚合注入 分析
    Thinkphp 5.1.7 parseData缺陷导致insert/update注入 分析
    Oracle笔记2
    Oracle笔记1
    k8s之helm入门
    k8s之自定义指标API部署prometheus
    k8s之资源指标API部署metrics-server
    k8s之调度器、预选策略及优选函数
  • 原文地址:https://www.cnblogs.com/tingtin/p/13552749.html
Copyright © 2011-2022 走看看