2023-12-29
Python
00

目录

封装
继承
方法重写
object类
多态
特殊方法和特殊属性

封装

面向对象的三大特征

  • 封装:提高程序的安全性
    • 将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。无需关心方法内部的具体实现细节,从而隔离了复杂难度。
    • 在python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个“_”。
  • 继承:提高代码的复用性。
  • 多态:提高程序的可扩展性和可维护性。
python
class Car: # 封装 def __init__(self,brand): self.brand=brand def start(self): print('汽车已启动') car=Car('宝马X5') car.start() print(car.brand) class Student: def __init__(self,name,age): self.name=name self.__age=age # 年龄不希望在类的外面使用,所以前面加了两个_ def show(self): print(self.name,self.__age) # 可以在类的内部使用__age stu=Student('张三',23) stu.show() print(stu.name) print(dir(stu)) # 列出对象的所有属性及方法 print(stu._Student__age) # 在类的外部可以通过 _Student__age 进行访问

继承

如果一个类没有继承任何类,则默认继承 object ,python 支持多继承,定义子类时,必须在其构造函数中调用父类的构造函数,语法格式 class 子类名( 父类1,父类2... )

python
class Person(object): # Person继承object类 def __init__(self,name,age): self.name=name self.age=age def info(self): print(self.name,self.age) class Student(Person): # Student 继承 Person 类 def __init__(self,name,age,stu_no): super().__init__(name,age) self.stu_no=stu_no class Teacher(Person): # Teacher 继承 Person 类 def __init__(self,name,age,teachofyear): super().__init__(name,age) self.teachofyear=teachofyear stu=Student('张三',23,'1001') teacher=Teacher('李四',31,10) stu.info() teacher.info() class inherit(Student,Teacher): # 多继承,inherit 同时继承了 Student和Teacher类 pass

方法重写

  • 如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写;子类重写后的方法中可以通过 super().xxx() 调用父类中被重写的方法。

    python
    class Person(object): # Person继承object类 def __init__(self,name,age): self.name=name self.age=age def info(self): print('姓名:{0},年龄:{1}'.format(self.name,self.age)) class Student(Person): # 定义的子类 Student 继承 Person 类 def __init__(self,name,age,score): super().__init__(name,age) self.score=score def info(self): super().info() print('分数:{0}'.format(self.score)) stu=Student('张三',23,'1001') stu.info()

object类

  • object 类是所有类的父类,因此素有类都有 object 类的属性和方法,内置函数 dir() 可以查看指定对象所有的属性; object 有一个 __str__() 方法,用于返回一个对于“对象的描述”,对应于内置函数 str() 经常用于 print() 方法,帮我们查看对象的信息,所以我们经常会对 __str__() 进行重写。

    python
    class Student: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '我的名字是{0},今年{1}岁'.format(self.name,self.age) stu=Student('张三',21) print(dir(stu)) print(stu) # 默认会调用 __str__() 这样的方法 print(type(stu))

多态

  • 多态就是“具有多种形态”,它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。

    python
    class Animal(object): def eat(self): print('动物要吃东西') class Dog(Animal): def eat(self): print('狗吃肉') class Cat(Animal): def eat(self): print('猫吃鱼') class Person(): def eat(self): print('人吃五谷杂粮') # def fun(animal): # 定义一个函数 # animal.eat() def fun(animal): animal.eat() # 调用函数 fun(Cat()) fun(Dog()) fun(Animal()) print('--------------') fun(Person())
  • 静态语言和动态语言关于多态的区别

    • 静态语言实现多态的三个必要条件: 继承方法重写父类引用指向子类对象
    • 动态语言的多态崇尚“鸭子类型”当看到一只鸟走起来像鸭子、游泳起来像鸭子,那么这只鸟可以被称为鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为。

特殊方法和特殊属性

名称 特殊方法
特殊属性 __dict__ 获得类对象或实例对象所绑定的所有属性和方法的字典
特殊方法
__len__() 通过重写__len__()方法,让内置函数len()的参数可以是自定义类型
__add__() 通过重写__add__()方法,可以使用自定义对象具有“+”功能
__new__() 用于创建对象
__init__() 对创建的对象进行初始化
  • 特殊属性

    python
    class A: pass class B: pass class C(A,B): def __init__(self,name,age): self.name=name self.age=age class D(A): pass # 创建C类的对象 x=C('tom',17) print(x.__dict__) # 实例对象的属性字典 print(C.__dict__) # 类对象可以查看到属性和方法 print(x.__class__) # <class '__main__.C'> 输出了对象所属的类 print(C.__bases__) # C类的父类类型的元素 print(C.__base__) # 类的基类 print(C.__mro__) # 查看类的层次结构 print(A.__subclasses__()) # 子类的列表
  • 特殊方法

    __add__()__len__() 特殊方法

    python
    a=20 b=100 c=a+b # 两个整数类型的对象的相加 d=a.__add__(b) print(c) print(d) class Student: def __init__(self,name): self.name=name def __add__(self, other): return self.name+other.name # 可以实现2个对象的相加 def __len__(self): return len(self.name) # 可以获取对象的长度 stu1=Student('张三') stu2=Student('李四') s=stu1+stu2 # 实现了两个对象的加法运算(因为在 Student 类中,编写 __add__() 特殊方法) print(s) s=stu1.__add__(stu2) print(s) lst=[11,22,33,44] print(len(lst)) # len是内置函数的len print(lst.__len__()) # 和上面的结果一样 print(len(stu1)) # 输出 stu1 的长度

    __init__()__new__() 特殊方法

    python
    class Person(object): def __new__(cls, *args, **kwargs): # 创建对象的方法 print('__new__被调用执行了,cls的id值为{0}'.format(id(cls))) obj=super().__new__(cls) print('创建的对象的id为:{0}'.format(id(obj))) return obj def __init__(self,name,age): # 初始化方法 print('__init__被调用了,self的id值为:{0}'.format(id(self))) self.name=name self.age=age print('object这个类对象的id为:{0}'.format(id(object))) print('Person这个类对象的id为:{0}'.format(id(Person))) # 创建Person类的实例对象 p1=Person('张三',18) print('p1这个Person类的实例对象的id为:{0}'.format(id(p1)))

类的浅拷贝与深拷贝

  • 变量的赋值操作: 只是形成两个变量,实际上还是指向同一个对象。

    python
    class CPU: pass class Disk: pass class Computer: def __init__(self,cpu,disk): self.cpu=cpu self.disk=disk # (1)变量的赋值 cpu1=CPU() cpu2=cpu1 print(cpu1,id(cpu1)) print(cpu2,id(cpu2)) # cup1和cpu2指向同一块内存地址
  • 浅拷贝:python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象。

    python
    #(2)类的浅拷贝 disk=Disk() #创建一个硬盘类的对象 computer=Computer(cpu1,disk) #创建一个计算机类的对象 #浅拷贝 import copy print(disk) computer2=copy.copy(computer) print(computer,computer.cpu,computer.disk) print(computer2,computer2.cpu,computer2.disk) #浅拷贝 对象包含的子对象不会拷贝
  • 深拷贝: 使用 copy 模块的 deepcopy 函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同。

    python
    #深拷贝 computer3=copy.deepcopy(computer) print(computer,computer.cpu,computer.disk) print(computer3,computer3.cpu,computer3.disk) #深拷贝的子对象也会拷贝一份

本文作者:柯南

本文链接:

版权声明:©2023 柯南 All rights reserved.