• python 3 基础之类和对象的创建、面向对象的三大特性


    面向对象简单理解:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程

    类:对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

      类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象

      如字典就是一类数据结构,字符串是一类数据结构,它们各自都具有相同的特征属性和方法

    对象:某个具体事物的存在,在现实世界看得见摸得着,对象归属于一类;创建一个对象需要依赖于类

    • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。类根据继承可以分为父类和子类
    • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
    • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
    • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
    • 实例变量:定义在方法中的变量,只作用于当前实例的类。
    • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,所以Dog也是一个Animal。(派生类相当于子类,基类相当于父类,只是称呼不同)
    • 实例化:创建一个类的实例,类的具体对象。
    • 方法:类中定义的函数。
    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法

    1、创建类和对象

      1.1、类

        经典类和新式类,从字面上可以看出一老一新,新的必然包含了更多的功能,是推荐的写法,从写法上区分:如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类

        创建一个类

    # 经典类1
    class Hhh:
        pass
    # 经典类2
    class Jor:
        pass
    # 新式类
    class Fa(object):
        pass

      1.2、创建一个对象

    # 自定义一个狗类(自定义类名一般遵循大驼峰命名)
    class Dog(object):
        # 定义一个方法(实例方法 或 对象方法)
        # 实例方法第一个参数为self(python默认的)
        # 实例方法 下划线 或小驼峰(公司的要求)
        def move(self):
            print('狗会吃骨头')
    # 使用自定义的类创建一个对象
    wangcai = Dog()
    # 调用狗类中的方法(想要使用其类中的方法,要使用这个类创建一个对象 使用对象调用其类里面的方法)
    wangcai.move()

    2、添加对象属性和判别同一个类创建的多个对象是否为同一个对象

      2.1、方法外添加对象属性

     1 # 定义一个Dog类
     2 class Dog(object):
     3     def eat(self):
     4         print('狗吃骨头')
     5     def zuoyong(self):
     6         print('狗会看家')
     7 
     8 # 使用类创建一个对象
     9 wang = Dog()
    10 # 在方法外赋予对象属性
    11 wang.name = '旺财'
    12 wang.age = 4
    13 wang.colour = '白色'
    14 print(wang.name)

      2.2、判别同一个类创建的多个对象是否为同一对象

      python中每创建一个新的对象,需要开辟一个内存空间,占用内存地址,而内存地址是唯一的,以此判断是否为同一个对象,不同对象开辟的内存地址也不同

     1 class Dog(object):
     2     def eat(self):
     3         print('狗吃骨头')
     4 # 使用类创建多个对象
     5 wang = Dog()
     6 wang1 = Dog()
     7 wang2 = Dog()
     8 # 用16进制查看对象的内存地址
     9 print(wang,wang1,wang2)
    10 # 用10进制查看对象的内存地址
    11 print(id(wang))
    12 print(id(wang1))
    13 print(id(wang2))
    14 
    15 ================================
    16 
    17 运行结果:<__main__.Dog object at 0x000002AFC4E21CC8>
    18  <__main__.Dog object at 0x000002AFC4E21D48>
    19  <__main__.Dog object at 0x000002AFC4E21D88>
    20 2953945685192
    21 2953945685320
    22 2953945685384

      运行结果是各不相同,证明同一个类创建的多个对象时唯一的

    3、面向对象的三大特征:封装、继承、多态

      3.1、封装

        顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容;对于面向对象来说,其实就是使用构造方法(__init__)将内容封装到对象中,然后通过对象直接或self间接获取被封装的内容

        封装的意义:

      1. 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;
      2. 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;
      3. 对类的属性和方法增加 访问权限控制

        

        3.1.1、通过 对象.属性 直接调用被封装的内容

    class Hero(object):
        # 构造方法
        def __init__(self, name, hp, atk):
            # 设置属性的值
            self.name = name
            self.hp = hp
            self.atk = atk
    # 创建一个对象
    laosun = Hero('俺老孙',100,10)# 实则就是把'俺老孙',100,10三个数据分别封装到name,hp,atk里
    # 通过对象直接调用
    print(laosun.name)

        3.1.2、通过 对象.方法 间接调用

    class Dog(object):
        # 构造方法
        def __init__(self, new_name, new_age, new_colour="白色"):
            # 给对象的属性赋值
            self.name = new_name
            self.age = new_age
            self.colour = new_colour
        def info(self):
            print("名字:%s" % self.name)
            print("年龄:%d" % self.age)
            print("毛色:%s" % self.colour)
    # 创建一个对象
    wang = Dog('黑狗',4,'黑色')
    # 间接调用
    wang.info()

      3.2、继承

        面向对象的继承和现实中的继承相似,面向对象的继承指的是类的继承,当一个类继承了另外一个类,被继承的类称之为父类,继承的类叫子类

        子类会继承父类的所有方法,属性;对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法

        在继承关系中,如果一个实例的数据类型是某个子类,那它也可以被看做是父类。但是,反过来就不行。

        继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树

        3.2.1、单继承

          只是继承一个父类

    # 创建一个类,继承于object
    class Dog(object):
        # 构造方法
        def __init__(self, new_name,):
            # 给对象的属性赋值
            self.name = new_name
        def info(self):
            print("名字:%s" % self.name)
    # 创建一个单继承的子类Heigou,继承类Dog
    class Heigou(Dog): def eat(self): print('黑狗血很贵听说') # 创建一个对象 wang = Dog('黑狗') hei = Heigou('大黑') # 根据对象调用类的方法 wang.info() hei.eat() # 根据对象调用父类的方法 hei.info() ============================================= 结果是成功调用父类的方法

        虽然子类没有定义__init__方法初始化属性,也没有定义实例方法,但是父类有。所以只要创建子类的对象,就默认执行了那个继承过来的__init__方法

        3.2.2、多继承

          子类继承多个父类(Python的类可以继承多个类,Java和C#中则只能继承一个类)

          多继承可以继承多个父类,也继承了所有父类的属性和方法
          注意:如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性mro的顺序来查找);多个父类中,不重名的属性和方法,不会有任何影响

    # 创建两个类,继承于object
    class Hero(object):
        def __init__(self, name, hp, atk):
            self.name = name
            self.hp = hp
            self.atk = atk
    class Dog(object):
        def __init__(self, new_name,):
            self.name = new_name
        def info(self):
            print("名字:%s" % self.name)
    # 创建一个多继承的类
    class Heigou(Dog,Hero):
        def eat(self):
            print('黑狗血很贵听说')
    # 创建一个对象
    wang = Dog('黑狗')
    hei = Heigou('大黑')
    # 调用父类的方法
    hei.info()
    # 利用子类的魔法属性__mro__查看属性和方法的查找顺序
    print(Heigou.__mro__)

         当多继承中多个父类都定义了相同的函数(包括函数名,函数内容),子类调用函数时调用的是哪个父类的函数?

        当类是经典类时,会按照深度优先方式查找(子类a继承父类b、c,c又继承了d,当子类调用相同方法时,先查找a是否有此方法,若无,调用b的,若b也无,查看b是否有继承父类,有则 继续查找b的父类 ,没有则开始查找c,c若无,找c的父类,无则继续找父类的父类)

        当类时新式类时,按照广度优先查找(子类a继承父类b、c,c又继承了d,当子类调用相同方法时,先查找a是否有此方法,若无,调用b的,若b也无,先查找a的第二个父类c,若无,继续查找a的父类,此级父类均没有才开始查找父类的父类)

        如下图

     注意:在上述查找过程中,一旦找到,则寻找过程立即中断,转而执行方法,不会再继续找

      

      3.3、多态(同一个对象,多种形态)

         所谓鸭子类型:看着像鸭子,我们就说它是鸭子

        3.3.1、变量的多态

          多态在python中其实是很不容易说明⽩的. 因为我们⼀直在⽤. 只是没有具体的说.

          比如. 我们创建⼀个变量a = 10 , 我们知道此时a是整数类型. 但是我们可以通过程序让a = "alex", 这时, a⼜变成了字符串类型. 这是我们都知道的. 但是, 我要告诉你的是. 这个就是多态性. 同⼀个变量a可以是多种形态

        3.3.2、类的多态

          在说明多态是什么之前,在 Child 类中重写 print_title() 方法:若为male,print boy;若为female,print girl

    class Person(object):
        def __init__(self,name,sex):
            self.name = name
            self.sex = sex
    
        def print_title(self):
            if self.sex == "male":
                print("man")
            elif self.sex == "female":
                print("woman")
    
    class Child(Person):                # Child 继承 Person
        def print_title(self):
            if self.sex == "male":
                print("boy")
            elif self.sex == "female":
                print("girl")
    
    May = Child("May","female")
    Peter = Person("Peter","male")
    
    print(May.name,May.sex,Peter.name,Peter.sex)
    May.print_title()
    Peter.print_title()

      当子类和父类都存在相同的 print_title()方法时,子类的 print_title() 覆盖了父类的 print_title(),在代码运行时,会调用子类的 print_title()

      这样,我们就获得了继承的另一个好处:多态。 

      多态的好处就是,当需要传入更多的子类,例如新增 Teenagers、Grownups 等时,我们只需要继承 Person 类型就可以了,而print_title()方法既可以直接继承,不重写(即使用Person的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种Person的子类时,只要确保新方法编写正确,而不用管原来的代码。

      用自己的话说多态:子类继承了父类,子类对父类的方法进行了重写,用子类进行创建对象,用对象可以调用子类的方法,也可以调用父类的方法,这就是多态

         

  • 相关阅读:
    oracle的wm_concat()方法与的排序问题,Oracle的 listagg 函数
    sql sever 常用的存储过程的写法或者说与Oracle中存过的异同点
    Oracle游标的使用
    oracle与sql sever的财务月份归属的问题
    sql sever使用习惯
    sqlsever 的存储过程的调试
    sql sever与Oracle的异同点
    单例模式
    线程 ---- 锁(生产者、消费者)
    IO 流理解实例
  • 原文地址:https://www.cnblogs.com/will-wu/p/13259898.html
Copyright © 2020-2023  润新知