本系列是学习 廖雪峰 Python3 教程 过程中记录的笔记,本篇文章记录 Python
中面向对象编程需要用到的基础知识点,包括类和实例、访问限制、数据封装、继承和多态,以及获取对象信息和类属性的介绍。
面向对象编程
- 面向对象编程——Object Oriented Programming,简称 OOP ;
- 面向对象的设计思想是抽象出 Class,根据 Class 创建 Instance;
- 一个 Class 既包含数据,又包含操作数据的方法,因此面向对象的抽象程度比函数要高;
- 面向对象编程的三大特点:数据封装、继承和多态;
类和实例
class
关键字用来定义一个类,类名的首字母大写,所有的类最终都会继承object
类;- 使用
class_name()
来生成一个具体的实例; __init__(self)
是类的构造方法,首个参数是self
,指向创建的实例本身,可以绑定各种属性;
访问限制
- 实现方式1——私有变量
__xxx
只有内部可以访问,外部不能访问;【注】__xxx__
这类是特殊变量,可以直接访问,私有变量命名就不要采用这种方式;
数据封装
- 类作为一个对象,对外屏蔽内部的属性和方法,外部代码可以通过调用实例变量的方法来操作数据;
继承
-
子类可以获得父类的全部方法,并可以自定义增加新的方法;
-
判断某个变量是否是某种类型可以使用
isinstance(variable, object)
,子类实例的类型也可以看作是父类的类型,反过来不行; -
动态语言的鸭子类型特点决定了继承不像静态语言那样必须是同种类型。
class Animal(): def run(self): # run方法 print("Animal is running!") class Dog(Animal): # 继承父类 pass class Cat(Animal): # 继承父类 pass def run_twice(animal): # 传入对象参数 animal.run() # 调用run方法 animal.run() a = Animal() d = Dog() c = Cat() # 继承:a自身有run方法,d,c会从继承父类里调用run方法,可以运行 # Dog Cat 中也可以编写自己的 run(),这样调用的时候就会优先使用子类的run() run_twice(a) run_twice(d) run_twice(c) print("继承") output——————————————— Animal is running! Animal is running! Animal is running! Animal is running! Animal is running! Animal is running!
多态
-
通过复写父类的方法实现多态;
-
通过拥有相同的方法实现多态;
-
开闭原则:对拓展开放,允许新增子类;对修改封闭,修改子类就只是对子类有作用;
class Animal(): def run(self): # run方法 print("Animal is running!") class Dog(): def run(self): # run方法 print("Dog is running!") class Cat(): def run(self): # run方法 print("Cat is running!") def run_twice(animal): #传入对象参数 animal.run() # 调用run方法 animal.run() a = Animal() d = Dog() c = Cat() # 多态:a,b,c类里都有run这个鸭子方法,a,b,c无论是什么类型都是鸭子,可以运行 run_twice(a) run_twice(d) run_twice(c) output—————————————— Animal is running! Animal is running! Dog is running! Dog is running! Cat is running! Cat is running!
获取对象的信息
-
判断类型使用
type()
和isinstance()
优先使用isinstance()
; -
dir()
可以查看对象的所有属性和方法,以list
展示; -
查看对象是否有某属性和方法可以使用
getattr()
hasattr()
setattr()
;【注】对私有属性和方法不起效果;a = Animal() s = Student('Morton', 'male') print(type(a), type(s)) # 判断对象的类型 print(isinstance(a, Animal), isinstance(s, Student)) # 判断对象的类型 print(hasattr(s, 'gender')) # 判断对象是由有某属性 print(getattr(s, 'gender')) # 获取该属性的值 print(hasattr(s, 'get_gender')) # 判断对象是由有该方法 print(getattr(s, 'get_gender')) # 获取该方法的内存地址 output—————————————— <class '__main__.Animal'> <class '__main__.Student'> True True True male True <bound method Student.get_gender of <__main__.Student object at 0x000001CBF844E278>>
实例属性和类属性
-
类属性是独立于实例存在的,可以在没有实例的条件下,通过类名称直接访问,也可以像普通实例属性一样,通过实例来访问;
-
【注】相同名称的实例属性将会屏蔽掉类属性,要避免这种操作;
# 为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加: class Student(object): count = 0 def __init__(self, name): self.name = name self.count = 5 # 实例属性,与类属性同名 Student.count += 1 # 类属性自增1 if Student.count != 0: print('测试失败!') else: bart = Student('Bart') if Student.count != 1: print('测试失败!') else: lisa = Student('Bart') if Student.count != 2: print('测试失败!') else: print('Students:', Student.count) print(bart.count, lisa.count) print('测试通过!') output———————————————— Students: 2 5 5 测试通过!