面向对象 - 类与对象-初始化方法-属性查找
一:面向过程 与 面向对象
面向过程编程
核心是
过程
二字,过程是解决问题的步骤,即:先干啥,后干啥基于该思想写程序就是在 设计一条条的流水线
优点:复杂的问题流程化、进而简单化
缺点:扩展性差
面向对象编程
核心是
对象
二字,对象是一个用来盛放数据与功能的容器基于该思想写程序就是在 整合程序
优点:进行解耦合,可扩展性强
缺点:编程复杂度高
二:面向对象的实现思路
1.基础版本
众所周知:面向对象中,对象就是存放数据和功能的容器,用来存放相关的数据。
现在先写一个基础版本的,非面向对象的学生数据和功能。
此时,学生的数据和功能是完全分开的,没有关联的,只有在调用
choose
函数的时候,才会传入学生的信息。
# 学生的数据
stu_name = 'xxq'
stu_age = 18
stu_gender = 'male'
# 学生的功能
def choose(name, age, gender):
print(f'学生:{name}正在选课,年龄:{age},性别:{gender}')
choose(stu_name, stu_age, stu_gender)
# 学生:xxq正在选课,年龄:18,性别:male
2.基于面向对象的思想进行改写
之前说到,对象就是一个数据和功能的容器,这里把学生的数据和功能放进一个字典里面。
字典里可以以键值对的形式来存放学生的数据,但是函数只能通过调用来实现,所以还是只有一个雏形。
# 学生的功能
def choose(stu_self):
print(f'学生:{stu_self["name"]}正在选课,年龄:{stu_self["age"]},性别:{stu_self["gender"]}')
# 字典
stu_obj = {
'name': 'xxq',
'age': 18,
'gender': 'male',
'choose': choose
}
stu_obj["choose"](stu_obj)
# 学生:xxq正在选课,年龄:18,性别:male
3.用类来实现
在用类来实现之前,我们需要先来了解一下类和函数调用的区别。
在定义一个函数之后,需要调用它,才会执行函数体的代码。
而类则和函数不同,类体代码会在类定义阶段立刻执行,然后将产生的名字放到类的名称空间中。
函数需要调用
def call():
print('调用了call函数')
call()
# 调用了call函数
类不需要调用
class Call:
print('调用了Call类')
# 调用了Call类
现在有三个学生,他们的学校和功能(选课功能)相同,其余的姓名、性别、年龄不同,如果每个对象中都要写上学校和功能,就会出现代码冗余(同样的代码出现多次),因此,可以将他们公共的数据和功能放在同一个容器中,需要用到了就去拿一下即可,这就引入了 类 这个概念。
例子 1 类的基本使用
class Student:
# 存放相同的数据
school = "Tinghua"
# 存放相同的功能
def choose(self):
print("正在选课")
# 实例化3个学生对象
stu_obj1 = Student()
stu_obj2 = Student()
stu_obj3 = Student()
# 赋值学生1的特有数据
stu_obj1.name = "张三" # 相当于:stu1_obj1.__dict__["name"] = "张三"
stu_obj1.age = 18
stu_obj1.gender = "male"
# 赋值学生2的特有数据
stu_obj2.name = "李四"
stu_obj2.age = 19
stu_obj2.gender = "female"
# 赋值学生3的特有数据
stu_obj3.name = "王五"
stu_obj3.age = 20
stu_obj3.gender = "male"
print(stu_obj1.__dict__)
print(stu_obj2.__dict__)
print(stu_obj3.__dict__)
'''
{'name': '张三', 'age': 18, 'gender': 'male'}
{'name': '李四', 'age': 19, 'gender': 'female'}
{'name': '王五', 'age': 20, 'gender': 'male'}
'''
例子 2 初始化方法的引入
之前的用来类的方法来实现的面向对象的思想,进行的数据的整合,把相同的数据和功能放进了一个类中,然后不同的对象再赋不同的值,但是整体看上去还是太麻烦了,每个对象都要单独赋值,也存在很多代码冗余。因此,我们可以定义一个函数
init
来调用对象中的属性,直接以参数传递的形式来赋值。
class Student:
# 相同的数据
school = "oldboy"
# 相同的功能
def choose(self):
print("正在选课")
# 实例化3个对象
stu_obj1 = Student()
stu_obj2 = Student()
stu_obj3 = Student()
# 定义一个函数来调用对象中的属性
def init(obj, x, y, z):
obj.name = x
obj.age = y
obj.gender = z
init(stu_obj1, '张三', 18, 'male')
init(stu_obj2, '李四', 19, 'female')
init(stu_obj3, '王五', 20, 'male')
print(stu_obj1.__dict__)
print(stu_obj2.__dict__)
print(stu_obj3.__dict__)
'''
{'name': '张三', 'age': 18, 'gender': 'male'}
{'name': '李四', 'age': 19, 'gender': 'female'}
{'name': '王五', 'age': 20, 'gender': 'male'}
'''
三:初始化方法
例子 3 初始化方法的使用
之前的
init
在类中其实是有一个__init__
方法的,可以直接将调用对象作为一个参数自动传入,省去了很多麻烦,只需要传需要的参数就可以了
class Student:
# 相同的数据
school = "oldboy"
def __init__(obj, x, y, z):
obj.name = x
obj.age = y
obj.gender = z
# return None # 这里如果要加return 只能返回None
# 相同的功能
def choose(self):
print("正在选课")
# 调用类:
# 1.创建一个空对象与类相关
# 2.把空对象、'张三', 18, "male"一起传给__init__方法,完成对象的初始化
# 3.赋值符号把初始化好的对象的内存地址绑定变量名stu_obj1
# 实例化3个对象,并传值
stu_obj1 = Student('张三', 18, "male")
stu_obj2 = Student('李四', 19, "female")
stu_obj3 = Student('王五', 20, "male")
print(stu_obj1.__dict__)
print(stu_obj2.__dict__)
print(stu_obj3.__dict__)
'''
{'name': '张三', 'age': 18, 'gender': 'male'}
{'name': '李四', 'age': 19, 'gender': 'female'}
{'name': '王五', 'age': 20, 'gender': 'male'}
'''
四:属性查找
在Python语法中,属性的查找是存在优先级的:先去对象自身找,找不到,再去进行实例化的类中找。
class Student:
school = 'Tinghua'
stu_obj = Student()
print(stu_obj.school)
# Tinghua
stu_obj.school = 'Peking'
print(stu_obj.school)
# Peking
在上述代码中,定义了一个
student
类,其中定义了一个变量名school = 'Tinghua'
实例化一个对象
stu_obj
之后,查找stu_obj
的school
,找到的是Student
类中的school
,因此输出是Tinghua
而在这之后,又单独给
stu_obj
的school
单独赋值了Peking
因此查找
stu_obj'
的school
,找到的是stu_obj
对象中的school
,因此输出是Peking
五:绑定方法
类中定义的函数是绑定给所有对象用的,绑定给谁就应该由哪个对象来调用 对象.绑定方法()会把对象当作第一个参数传入 类.函数()就是一个函数的玩法,没有自动传参的效果
class Student:
school = "oldboy"
def __init__(obj, x, y, z):
obj.name = x
obj.age = y
obj.gender = z
def choose(self):
print("%s 正在选课" % self.name)
stu_obj1 = Student('张三', 18, "male")
stu_obj2 = Student('李四', 19, "female")
stu_obj3 = Student('王五', 20, "male")
print(Student.choose)
print(stu_obj1.choose)
print(stu_obj2.choose)
print(stu_obj3.choose)
'''
<function Student.choose at 0x000001AFAF5A68C8>
<bound method Student.choose of <__main__.Student object at 0x000001AFB6690AC8>>
<bound method Student.choose of <__main__.Student object at 0x000001AFB788B2E8>>
<bound method Student.choose of <__main__.Student object at 0x000001AFB78FB6A0>>
'''