研究生基础-Python快速入门(终)------面向对象
文章目录
编程类型
面向过程
面向过程就是一种以过程为核心的编程模式。把要完成的程序拆分为几个步骤,然后按照顺序写代码并执行。代表语言:C语言
面向对象
面向对象会把事物抽象成对象,给每个对象赋予属性和方法,在运行过程中让对象都去执行自己的方法。代表语言:Java、Python
面向对象编程
类和对象
-
类:具有相同属性和功能的一类事物,是抽象的,在现实生活中不存在具体概念
-
对象:类的具体体现,是面向对象编程的核心,是具体的,在现实生活中存在具体概念
例子:动物(类):猫(对象)、狗(对象)
语法结构
自定义类的语法结构:
python
class 类名():
具体代码
python
# 创建Person类
class Person():
pass
# 创建Cat类
class Cat():
pass
创建对象的语法结构:
python
对象名 = 类名()
python
# 创建一个Person类的对象
people = Person() # people就是Person类的对象
print(type(people)) # 会输出<class '__main__.Person'>
类的属性和方法
- 属性:对象的特征描述,其本质为类中定义的变量
- 方法:对象具备的某些行为特征。其本质为函数
- 类属性:定义在类中、方法之外的属性,可以通过 "类名.属性名" 来访问,其本质是类这一个抽象概念共有的属性。例如:猫这个类共同的属性"有尾巴"
- 实例属性:从属于实例对象的属性,一般在
__init__()方法中定义:self.实例属性名 = 初始值,本质上其实是将抽象的类化为具体的对象需要用到的一些共性属性。例如:Person类中有name属性,在创建"小明"这个对象时,就需要对Person中的name属性传参"小明",将"小明"这个对象具体化 - 类方法:使用装饰器
@classmethod来声明,第一个参数通常被命名为cls,它指向类而不是实例(对象) - 实例方法:定义在类中的函数,且自带参数
self,对象可以调用此方法 - 静态方法:使用装饰器
@staticmethod来声明,是类中的独立函数
python
# 类属性和方法示例
class Person():
height = 180 # 类属性
weight = 130 # 类属性
def __init__(self,name,age): # 初始方法,name、age是方法的参数,是局部变量,作用域为整个__init__方法 self表示的是实例本身
self.name = name # 左侧self.name为实例属性,右侧为局部变量name,两者可以相同
self.age = age
# 以上的目的是定义实例,使其都能使用后续的实例方法。其实就是一个定义的作用。比如,创建一个对象为(小明,20),这个对象会先把"小明"和"20"这个参数传给类进行对象初始化,这个对象就可以调用属于它的示例方法了,就是通过传参将类模板变成了一个可以使用的对象(将抽象的事物具体化)
def sing(self): # 实例方法
print("我会唱歌")
def jump(self): # 实例方法
print("我会跳远")
def show(self): # 实例方法
print(f"我叫{self.name},今年{self.age}岁") # 必须使用实例属性,单独使用name无效
# 类方法 不能调用实例属性和实例方法,cls指向的是类
@classmethod
def class_method(cls):
print(f"我的身高为{cls.height}")
# 静态方法 静态方法没有访问类或者实例的特殊参数
@staticmethod
def add(a,b): # 这里定义了一个相加方法,但是此方法没有访问这个类中任何相关参数,此方法为静态方法
result = a+b
return result
python
# 创建对象示例
person = Person("小明",20) # init方法中有多个形参,self为自带参数,指向的是实例,无需传入任何参数,实际上是从self后面的属性开始传参
print(Person.height) # 类属性, 使用类名加.即可调用
print(person.name) # 实例属性,使用对象名加.即可调用
person.jump() # 调用实例方法
person.show() # 调用实例方法
Person.class_method() # 类方法
Person.add(100,20) # 静态方法
python
# 根据类创建多个对象
per_1 = Person("小红","21")
per_2 = Person("小王","22")
per_3 = Person("小刚","23")
print(per_1.name)
print(per_2.name)
print(per_3.name)
# 循环打印三个对象的姓名、年龄
lst_1 = [per_1,per_2,per_3]
for item in lst_1:
print(item.name)
print(item.age)
python
# 创建类并实例化对象
class House():
def __init__(self,size,height,value):
self.size = size
self.height = height
self.value = value
def sleep(self):
print("到家就要睡觉")
h_1 = House(150,3,300)
print(h_1.size)
h_1.sleep()
h_2 = House(120,3,240)
h_1.age = 10 # 给h_1动态绑定实例属性,这样做会使h_1自动添加age属性
print(h_1.age) # 会输出1
def house_type():
print("这是一个木屋")
h_1.Jt = home_type # 函数赋值,Jt为h_1对象的方法
h_1.Jt() # 输出"这是一个木屋"
封装、继承、多态
封装
-
封装是面向对象编程最重要的特性。封装就是将数据和功能整合在一起,针对封装到对象或者类中的属性,可以严格控制在类外部对它们的访问,即隐藏属性和开放接口
-
封装的优点
- 封装可以提高代码的安全性,防止外部代码直接访问对象的内部状态,外部只能通过已经定义好的接口操作对象
- 封装使得类的内部细节可以随时修改,不会影响外部调用者的其他内容
- 封装可以提供清晰的外部接口,减少调用者需要了解的类的细节,降低调用难度
-
封装通过定义
私有属性和方法和公共接口方法实现- 私有属性和方法:使用编程语言提供的特殊语法(如 Python 中使用双下划线
__开头的属性或方法)来限制对属性和方法的访问,使其只能在类的内部被访问 - 公共接口方法:提供公有的方法来访问和修改私有属性,实现对属性的控制和保护
- 私有属性和方法:使用编程语言提供的特殊语法(如 Python 中使用双下划线
-
访问限制(对应私有属性和方法中的特殊语法)
-
单下划线开头:属性或方法以单下划线开头,表示其受保护,在类的内部和子类中可以被访问,但是不建议直接访问,此种命名约定被称为"受保护的(protected)
-
双下划线开头:属性或方法以双下划线开头,表示其是私有状态,只能在类的内部访问,外部无法直接访问,此种命名约定被称为"私有的(private)"
-
双下划线开头并结尾:此类被称为"魔法方法",如常见的 :
__init__、__del__等。此类方法在类或对象进行特定的操作时会自动被调用,可以使用或重写这些方法给自定义的类添加各种特殊的功能来满足自己的需求。
python# 访问限制示例 class Person(): def __init__(self,name,age,height): self._name = name # self._name是受保护的,只能本类和子类访问 self.__age = age # self.__age是私有的 只能在类的内部访问 self.height = height # 实例属性,在类的内部,外部,子类都可以访问 p_5 = Person("小明",20,180) print(p_5._name) # 调用受保护的实例属性 print(p_5.__age) # 调用私有的实例属性,会报错 print(p_5._Person__age) # 强制调用私有属性,输出"20",但不推荐 print(dir(p_5)) # 查看对象的所有属性和方法 -
-
主要概念
- 类:抽象的概念,现实世界不存在
- 对象:具体的概念,现实世界存在
继承
-
继承是一种类与类之间的关系,指的是一个类从另一个类获取属性和方法的信息。实现继承的类称为子类,被继承的类称为父类
-
继承使子类具有父类的各种属性和方法,不需要在子类中重复编写相同的代码,提高代码的复用性
-
继承特性
- 一个子类可以继承多个父类:Python支持多重继承,一个类可以继承多个类的属性和方法
- 一个父类可以有多个子类:一个父类可以被多个子类继承,形成类的层次结构
- 所有类默认继承
object类:一个类没有明确继承任何类,它默认继承自Python的根类object类
-
继承格式
pythonclass 类名(父类名): pass -
继承特点
- 覆盖方法:子类可以重写父类的方法,以实现特定的行为模式
- 代码重用:允许子类重用父类的代码,提高代码复用率
- 扩展性:子类可以在继承父类的基础上添加新的属性和方法,增强类的功能
-
继承类型
- 单继承:一个子类只继承一个父类
- 多继承:一个子类继承多个父类
- 多层继承:一个子类继承自另一个子类,而后者又继承自一个父类
- 混合继承:结合了单继承和多继承的特性,使得子类同时具有多个父类的特征
python
# 继承示例
class Person(): # 定义一个Person类 默认继承object类
def __init__(self,name,age):
self.name = name # 定义实例属性 name
self.age = age
def fun(self):
print(f"我是{self.name},今年{self.age}岁")
class sport_person(Person):
def __init__(self, name, age):
super().__init__(name, age) # 调用父类Person的初始化方法,传入姓名和年龄
print(f"我叫{self.name},今年{self.age}岁,我是运动员")
class sing_person(Person):
def __init__(self, name, age):
super().__init__(name, age)
print(f"我叫{self.name},今年{self.age}岁,我是歌手")
p1 = sport_person("小明",22) # 创建 sport_person 类的实例,姓名为 "小明",年龄为22
p2 = sing_person("小红",25)
p1.fun() # 调用父类的 fun 方法输出个人信息
# 多继承示例
class A():
def printA(self): # 无实例属性,可以不写初始化方法
print("输出A")
class B():
def printB(self):
print("输出B")
class C(A,B):
def printC(self):
print("输出")
c1 = C() # 创建C类的实例
c1.printA() # c1可以调用A类的方法 会输出"输出A"
多态
- 多态指的是一类事物有多种形态。动物类可以有猫、狗等多个子类
- 多态表现为同一个方法或操作,在不同的对象上有不同的表现形式
- 多态是一种使用对象的方式,子类可以重写父类的方法,当调用相同的方法时,不同子类的对象会表现出不同的行为
- 多态的优点
- 易于扩展:只需要新增子类并重写父类方法,外部代码可以无缝适应新增的子类,提升代码的可扩展性、维护性
- 代码简洁:多态使得父类的接口能够处理不同类型的对象,代码更加简洁且具有兼容性
python
# 多态示例
class Animal: # 定义动物类
def eat(self):
pass
class Dog(Animal): # 定义动物类之一:狗
def eat(self):
print('狗吃肉')
class Cat(Animal): # 定义动物类之一:猫
def eat(self):
print('猫吃鱼')
class Pig(Animal): # 定义动物类之一:猪
def eat(self):
print('猪吃菜')
#实例化三个对象
dog=Dog()
cat=Cat()
pig=Pig()
def Eat(animal): # 定义一个Eat函数,这个Eat函数传参为对象,可以调用对象的eat方法
animal.eat()
# 调用 Eat 函数并传入不同的动物实例
Eat(dog) # 输出"狗吃肉"
Eat(cat) # 输出"猫吃鱼"
Eat(pig) # 输出"猪吃菜"
魔法方法
对应"封装"中的访问限制中的双下划线开头并结尾方法
- 魔法方法(也称为特殊方法或双下划线方法)是Python中一些具有特殊功能的方法,它们以双下划线
__开头和结尾
python
# 魔法方法示例
class List_1: # 定义一个列表类
def __init__(self, lst): # 传入的实参也为列表
"""
初始化方法
参数:
lst (list): 要包装的列表。
"""
self.lst = lst
def __getitem__(self, index):
"""
获取指定索引位置的元素。
参数:
index (int): 要获取元素的索引。
返回:
该索引位置的元素。
"""
return self.lst[index]
def __delitem__(self, index):
"""
删除指定索引位置的元素。
参数:
index (int): 要删除元素的索引。
"""
del self.lst[index]
def __len__(self):
"""
返回列表的长度。
返回:
列表的长度。
"""
return len(self.lst)
def append(self, item):
"""
向列表末尾添加一个新元素。
参数:
item: 要添加的新元素。
"""
self.lst.append(item)
python
# 创建一个列表
my_list = [1, 2, 3, 4, 5]
# 实例化 List_1类对象,传入列表作为参数
wrapper = List_1(my_list)
# 使用魔法方法获取列表中的第三个元素
print(wrapper.__getitem__(2)) # 输出3
# 使用魔法方法获取列表的长度
print(wrapper.__len__()) # 输出5
# 使用魔法方法向列表末尾添加一个新元素
wrapper.append(6)
# 查看列表的内容
print(wrapper.lst) # 输出[1, 2, 3, 4, 5, 6]
# 使用魔法方法获取列表的长度
print(wrapper.__len__()) # 输出6
# 使用魔法方法删除列表中的第一个元素
wrapper.__delitem__(0)
print(wrapper.lst) # 查看列表内容,输出[2, 3, 4, 5, 6]
print(wrapper.__len__()) # 查看现在列表长度,输出5
表的长度
print(wrapper.__len__()) # 输出5
# 使用魔法方法向列表末尾添加一个新元素
wrapper.append(6)
# 查看列表的内容
print(wrapper.lst) # 输出[1, 2, 3, 4, 5, 6]
# 使用魔法方法获取列表的长度
print(wrapper.__len__()) # 输出6
# 使用魔法方法删除列表中的第一个元素
wrapper.__delitem__(0)
print(wrapper.lst) # 查看列表内容,输出[2, 3, 4, 5, 6]
print(wrapper.__len__()) # 查看现在列表长度,输出5