• 16-面向对象之语法(1)


    1. 举例:

    class People(self,name,age):
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def run(self):
            print("I can run")
            
    p1 = People("Tom", 22) //实例化,得到一个instance
    # self的含义代表“当前这个对象,这个instance”,与当前这个class区分开
    

    2. _init_() 和 _new_() 的功能与区分:

    • _new_() 是创建instance(叫对象或者实例都可以)
    • _init_() 是初始化上面创建好的instance

    我个人觉得:init加上new,近似等价于java里面的构造方法,当实例化class得到了一个instance时,系统自动调用new和init

    • 定义class的fun时需要传入self参数,但是调用时系统自动传入self,这个参数无须用户处理:定义时要形参写self, 但是真正传实参时忽略它。
    • _str_() 的激发时机:当系统要print(某对象)时,会自动激发此函数
    • 以上三个魔术方法,都可以用户自定义或者不管(系统默认有)

    3. 属性私有化:

    __name,__run() 属性或者方法名前面两个下划线,即变成只有class内部能够访问的私有属性
    (不是完全没办法class外部访问,只是建议私有属性和方法不要在class外部直接访问)

    4. 继承:

    class Student(People) #就是这样简单地继承了People
    实现的效果:

    • Student这个class默认拥有People所有的公开属性及公开方法;
    • 私有属性和方法不能被继承;
    • 子类继承父类的公有属性的本质:子类默认继承了父类的_init_() ;所以如果子类重写了_init_(),子类就去调用自己的_init_(),就不一定会继承父类的所有公共属性。这一点切记!看透继承公共属性的本质!
    • 继承父类的公共方法的本质:也是默认继承了父类所有的公共方法。如果子类重写了这些方法,也是直接先去调用自己的方法。
    • 故而,一切继承行为的本质:有没有默认调用父类的某个方法,如果子类重写了,那就去调用自己的方法,那就不一定能得到父类所有的东西。

    默认所有类都有一个基类:object(都是默认继承自object),默认继承objext的所有属性和方法。

    重写:

    • 子类与父类的方法名相同,子类即重写了此方法,优先去调用自己的方法。
    • 子类重写了父类的方法之后,依旧希望调用父类的方法,有以下方案:
    • super().父类方法名(实参)
    • super(子类名,self).父类方法名(实参)
    • 父类名.父类方法名(self,实参)
    class Animal(object):
        def __init__(self,name):
            self.name = name
            print("Animal init
    ")
        
        
    class Cat(Animal):
        def __init__(self):
            print("Cat init
    ") #再执行自己的逻辑
            
            
    class Dog(Animal):
        def __init__(self,color): #实例化对象需要传入color
            super().__init__("DogName") #调用父类的__init__(参数要根据父类的init形式写)
            print("Dog init
    ")
            self.color = color
            
    class Pig(Animal):
        def __init__(self): #实例化对象需要传入color
            super(Pig,self).__init__("PigName") #调用父类的__init__(参数要根据父类的init形式写)
            print("Pig init
    ")
            
    class Chiken(Animal):
        def __init__(self): #实例化对象需要传入color
            Animal.__init__(self,"PigName") #调用父类的__init__(参数要根据父类的init形式写)
            print("Chiken init
    ")
            
            
    c = Cat()#因为Cat的init重写了,根据重写的init的参数形式来构造实例
    #print(c.name) #Cat 虽然继承了Animal,Animal有name,但是此处Cat无法获得name
    
    d = Dog("black")
    
    p = Pig()
    
    c = Chiken()
    
    
    #本文的__init__()可换成父类的任意公共方法
    #而父类的公共属性的继承的本质:一定要记住:是由于继承父类的__init__()而得到的,
    #没有继承父类的__init__()就无法继承父类的公共属性
    

    5. 多继承:

    • class C(B,A):写在前面的父类优先级高(B比A高),当前这个class本身的优先级最高(C>B>A),这个class的实例优先级最低(C>B>A>The_instance_of_C)。__mro__是当前class的类级别的属性,标识了当前类体系里面优先级的高低。

    6.多态:

    • 多态本意是:强类型语言中,某变量声明为A类型,使用时“看起来不是”A类型:看起来有多种形态。
    • python任何变量皆对象(包括函数都是instance, int 也是instance),所以多态无意义
    • python强调“鸭子类型”:只要具备相同的方法,每个对象都认为是“相似”的。

    7.类属性与实例属性

    • 类属性属于class,它在内存中只有一个副本。可以被所有instance使用, 具体说即使没有instance,这个类属性依旧存在,它与instance无关!(与java的static变量相似)。

    • 实例属性:必须用self.attr标识,隶属于一个instance,与这个instance共存亡,与当前的class没有关系。

      class Person(object):
      name = "person" #公有的
      __passwd = 2018 #私有的

      def init(self,sex):
      self.sex = sex #self.sex是实例属性,必须用self标识:与对象共存亡

      print(Person.name,' ')

      p1 = Person("female")
      print(p1.sex) #实例属性:生命周期与instance相关
      print(p1.name)
      print(Person.name,' ') #类属性:生命周期与class相关

      p2 = Person("male")
      print(p2.sex)
      print(p2.name)
      print(Person.name,' ')

    8.类的静态方法与类方法:

    1. 三个重要结论:

    • 类属性和类方法,都是属于class,所以能被子类继承。继承这个操作是class层次的行为
    • 类属性和类方法可以通过类的instance或者类名来调用
    • 类属性的修改和删除只能通过类名
      *类方法必定有个形参(cls) {类比普通方法必定有个self}
      *类方法使用@classmethod 标识

    2. 静态方法(类方法中的特例):

    • @staticmethod标识,形参可以为空,但一旦传入多少形参,就要传入多少实参

      class A(object):
      name = "hao" #类属性

      def test_1(self): #普通方法
      print("A的普通方法 test_1")

      @classmethod #标识类方法的关键字,{类比java的注解}
      def test_2(cls): #cls,标识当前这个class
      print("A的类方法 test_2")

      @staticmethod #标识类的静态方法
      def test_3(): #形参可以为空,但是若写了就必须传入全部参数,因为这里没有self或者cls
      print("A的类方法静态方法 test_3")

      print(A.name)

      A.test_1() #普通方法不能通过类名调用

      A.test_2()
      A.test_3()
      print(' ')

      a = A()
      print(a.name)
      a.test_1()
      a.test_2()
      a.test_3()

    3. 普通实例方法:

    • 必定有个形参self,实参却不用自己传入self(系统自动传入)
    • self引用的即可以是类属性,也可以是实例属性 (具体情况具体分析)
    • 而对于类方法,cls引用的一定是类属性和类方法;对于静态方法,需要用类名来引用类属性和类方法(也只能访问类属性和类方法)。

    4. 再次回顾子类重写父类的方法,对于公共属性和公共方法的影响:

    • 如果没有重写行为,默认继承了父类所有的公共属性和公共方法。
    • 如果子类对_init_()执行重写,那么创建的对象优先执行子类重写后的_init_(), 所以有些父类的公共实例属性可能不能被继承到子类,但类属性不受影响,依旧可以继承下来,因为它不在__init__里面
    • 如果子类对哪个公共方法进行重写,那么子类的对象就首先只执行重写后的那个方法 {这一点上,无论方法是普通方法还是类方法}

    9. _del_():类比java的析构方法

    某对象最后一次被引用完毕,自动执行_del_(),系统回收这个对象的内存空间时

  • 相关阅读:
    国密算法 SM3 摘要计算 java版
    《Java架构师的第一性原理》41存储之MySQL第10篇数据库切分
    《Java架构师的第一性原理》41存储之MySQL第9篇MySQL主从复制
    《Java架构师的第一性原理》41存储之MySQL第8篇索引
    《Java架构师的第一性原理》41存储之MySQL第7篇SQL执行原理
    《Java架构师的第一性原理》41存储之MySQL第5篇事务
    《Java架构师的第一性原理》41存储之MySQL第6篇锁
    《Java架构师的第一性原理》41存储之MySQL第4篇MySQL日志系统(BinLog、RedoLog、UndoLog)
    《Java架构师的第一性原理》41存储之MySQL第3篇存储引擎MyISAM、InnoDB
    《Java架构师的第一性原理》41存储之MySQL第2篇MySQL逻辑架构
  • 原文地址:https://www.cnblogs.com/LS1314/p/8504451.html
Copyright © 2020-2023  润新知