第二模块 类的笔记_汇总 第一篇
@
目录
Python: 面向对象编程基础
- 面向对象编程
( Object Oriented Programming, OOP)
是一种程序设计理想 - 在Python中, 所有数据类型都被视为对象, 自定义对象的数据类型就是面向对象中类
class
的概念
类编程风格, 标准
- 关键词:
类
,实例
,方法(属性)
,属性: 形参变量
,实例变量的值
- 扩展知识: 包含类的
py
文件被称为模块
,包
- 书写规范:
- 类名应采用
驼峰命名法
, 即:将类名的每个单词的首字母大写,而不是使用下划线
. - 实例名和模块名都采用小写格式, 多个单词拼接时,在单词之间使用下划线
- 对于每个类, 都应该在类定义之后包含一个
文档字符串 docstring
进行简要的描述类的功能,甚至可以加上使用方法 - 空行: 一个空行分隔方法, 两个空行分隔类
- 导入模块时, 先导入标准库, 再使用空行区分自定义模块
- 类名应采用
类和实例
- 类
Class
: 类是抽象的模板 - 实例
Instance
: 实例是根据类创造出来的一个个具体的对象
(数据类型)
# 类, 抽象的模板
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print(f"{self.name}'s age is {self.age}")
# 实例, 具体化类的对象
jim = Student("Jim", "20")
jim.print_age() # 调用类方法
Jim's age is 20
方法
构造方法__init__
(self, name, age)
- 方法: 在类中的函数被称为
方法
,在类中的方法
区分于函数
的地方就是调用的方式 - 方法的圆括号内是形参:
- 形参
self
位于其他形参前,区别于普通函数,表示创建的实例本身. Python在调用__init__
方法时将自动传入实参self
. - 形参
name
,age
: 通过实例对象向模板
传递形参变量
的值
, 该变量就被关联到当前创造的实例
- 形参
访问属性
# 接上一个代码示例
jim.name
'Jim'
jim # 查看类在内存的位置
<__main__.Student at 0x1d67c42b1d0>
- 查看类在内存的位置
- 访问实例的属性
- 在编写类的过程中常见性会直接调用类,而没有进行实例化造成输出内容为
内存的位置
调用方法
- 可以按照需求根据类创建任意数量的实例, 对属性进行各类的数据封装
lili = Student("Lili", "20")
lili.print_age()
blue = Student("Blue", "20")
blue.print_age()
Lili's age is 20
Blue's age is 20
面向对象的特性:
1.class
类
: 一个类是对拥有相同属性的对象的抽象. 类拥有类的属性和类的方法
2. object
对象
: 一个对象即是一个类的实例化的实例. 这个过程就实例化
3. Encapsulation
封装
: 在类中对数据的赋值, 隐藏实现细节,使得代码模块化
4. Inheritance
继承
: 扩展已存在的代码模块(类)
,它们的目的都是为了代码重用
5. Polymorphism
多态
: 接口重用。类在继承和派生的时候,保证使用"家谱"中任一类的实例的某一属性时的正确调用
案例:
# -*- coding:utf-8 -*-
# 演示一个汽车类
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
2016 Audi A4
直接修改属性的默认值
# -*- coding:utf-8 -*-
# 演示一个汽车类
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 增加汽车里程数,并设置初始值为0
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
def read_odo(self):
"""打印一条关于汽车里程数的消息"""
print(f"{self.make} " + str(self.odometer_reading) + "miles on it ")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 30 # 传递一个属性的值
my_new_car.read_odo()
2016 Audi A4
audi 30miles on it
通过方法修改属性的值
# -*- coding:utf-8 -*-
# 演示一个汽车类
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 增加汽车里程数,并设置初始值为0
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
def update_odo(self, mileage):
"""使用方法来修改属性的值"""
self.odometer_reading = mileage
def read_odo(self):
"""打印一条关于汽车里程数的消息"""
print(f"{self.make} " + str(self.odometer_reading) + "miles on it ")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odo(50) # 类方法赋值给形参属性
my_new_car.read_odo()
2016 Audi A4
audi 50miles on it
针对类方法进行逻辑判断,从而获得自定义传参效果
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 500 # 增加汽车里程数,并设置初始值为0
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
def update_odo(self, mileage):
"""
设定里程表初始指定值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading: # 构造函数中的形参默认值
self.odometer_reading = mileage
else:
print("不可以偷偷修改里程数哟! ")
def read_odo(self):
"""打印一条关于汽车里程数的消息"""
print(f"{self.make} " + str(self.odometer_reading) + "miles on it ")
def increment_odo(self, miles):
"""将里程表的值增加指定量"""
self.odometer_reading += miles
used_car = Car('honde', 'outback', 2006)
print(used_car.get_descriptive_name())
used_car.update_odo(5250) # 类方法赋值给形参属性
used_car.read_odo()
used_car.increment_odo(50) # 控制用户随意修改里程数
used_car.read_odo()
2006 Honde Outback
honde 5250miles on it
honde 5300miles on it
继承, 重写父类的方法
- 目标: 减少重复性工作
- 子类继承父类的所有属性和方法, 同时还可以自定义自己的属性和方法
- 初学时经常性出现的错误,各种难过(小彩蛋)
案例: 在汽车类的基础上,个性化创建一类电动汽车
# -*- coding:utf-8 -*-
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 增加汽车里程数,并设置初始值为0
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
def update_odo(self, mileage):
"""
设定里程表初始指定值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading: # 构造函数中的形参默认值
self.odometer_reading = mileage
else:
print("不可以偷偷修改里程数哟! ")
def fill_gas_tank(self):
"""子类会重写"""
print("我是烧油的! ")
def read_odo(self):
"""打印一条关于汽车里程数的消息"""
print(f"{self.make} " + str(self.odometer_reading) + "miles on it ")
def increment_odo(self, miles):
"""将里程表的值增加指定量"""
self.odometer_reading += miles
class ElectCar(Car):
"""获取Car类的属性,并定义一个新的子类电动汽车"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 3.0的写法
"""super(ElectCar, self)__init__(make, model, year), 2.7的写法"""
self.battery_size = 70 # 子类的特有属性
def describ_battery(self):
"""输出一条关于电池的消息"""
print("This ElectricCar has a " + str(self.battery_size) + "-kWh battery")
def fill_gas_tank(self):
"""重写父类方法"""
print("我不需要油箱! ")
my_elect_car = ElectCar("tesla", "model's", 2018)
print(my_elect_car.get_descriptive_name())
print("这里是分隔符区分实例方法故障,送新手".center(50, "*"))
print(my_elect_car.get_descriptive_name) # 注意上下两行print的区别,别漏了花括号
my_elect_car.describ_battery()
my_elect_car.fill_gas_tank()
2018 Tesla Model'S
****************这里是分隔符区分实例方法故障,送新手****************
<bound method Car.get_descriptive_name of <__main__.ElectCar object at 0x000001D67C515358>>
This ElectricCar has a 70-kWh battery
我不需要油箱!
分离类, 父类重写
- 当类方法的某一个属性不断被定义时,可以将这些属性和方法提取出来,单独建立一个类
# -*- coding:utf-8 -*-
class Car:
"""模拟汽车"""
def __init__(self, make, model, year):
"""初始化描述汽车的属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0 # 增加汽车里程数,并设置初始值为0
def get_descriptive_name(self):
"""返回一个汽车的描述性信息"""
full_name = str(self.year) + " " + self.make + " " + self.model
return full_name.title()
def update_odo(self, mileage):
"""
设定里程表初始指定值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading: # 构造函数中的形参默认值
self.odometer_reading = mileage
else:
print("不可以偷偷修改里程数哟! ")
def fill_gas_tank(self):
"""子类会重写"""
print("我是烧油的! ")
def read_odo(self):
"""打印一条关于汽车里程数的消息"""
print(f"{self.make} " + str(self.odometer_reading) + "miles on it ")
def increment_odo(self, miles):
"""将里程表的值增加指定量"""
self.odometer_reading += miles
class Battery:
"""将电池从ElectCar类中独立出来重写一个类"""
def __init__(self, battery_size=70):
"""初始化电池属性"""
self.battery_size = battery_size
def describ_battery(self):
"""对电池容量进行描述"""
print("This ElectricCar has a " + str(self.battery_size) + "-kWh battery")
class ElectCar(Car):
"""获取Car类的属性,并定义一个新的子类电动汽车"""
def __init__(self, make, model, year):
super().__init__(make, model, year) # 3.0的写法
"""super(ElectCar, self)__init__(make, model, year), 2.7的写法"""
self.battery = Battery() # 初始化类在形参中调用Battery类方法
def fill_gas_tank(self):
"""重写父类方法"""
print("我不需要油箱! ")
my_elect_car = ElectCar("tesla", "model's", 2018)
print(my_elect_car.get_descriptive_name())
my_elect_car.battery.describ_battery() # 实例中直接调用了Battery的方法
2018 Tesla Model'S
This ElectricCar has a 70-kWh battery
多态:
- Python天生多态, "鸭子类型"
- Pyhon 很多语法都是支持多态的.比如 len(), sorted()。 你给len传字符串就返回字符串的长度。 传列表就返回列表长度
- 还没有太大的印象,等后期再回顾时再做一些额外的补充
class Animal(object):
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return "Neow!"
class Dog(Animal):
def talk(self):
return "Woof!...Woof!"
D = Dog("D1")
C = Cat("C1")
def Animal_talk(obj):# 一个接口.多种形态.
print(obj.talk())
Animal_talk(D)
Animal_talk(C)
Woof!...Woof!
Neow!
未完待续,待补充内容如下:
- 元编程
- 属性: 私有属性, 共有属性, 成员属性
- 特殊方法:
__init__ : 初始化函数, 将各种属性绑定到self
__slots__: 限制实例的动态属性, 减少内存消耗, tuple类型
__eq__: 比较对象是否相等
@classmethod :会将类本身作为第一个参数传入
@staticmethod: 定义一个静态方法, 类可以不用实例化就可以调用方法