一,概念理解
面向对象是相对于面向过程来说的,程序可以说是算法+数据两部分组成,面向过程会偏向于算法,而面向对象会偏向于数据。
在要实现某个功能,面向对象和面向过程的区别?
- 面向过程:是去想从开始到结束应该有哪些连续的步骤,把任务分解成一个个带参数的函数,然后再去执行这些函数
- 面向对象:是去分析参与问题的有哪些实体,把事物抽象成对象的概念,通过调用这些实体的属性和方法解决问题
python属于典型的面向对象的编程语言,比较典型的如前面各数据类型的操作方法,它是通过类和对象的方法来组织代码的完成,而不是像面向过程语言那样直接调用函数,像调用int()其实也是类的实例化过程
二,类的概念与定义
如在学校中有学生和老师两类人,这两类人有各自的身高、体重、年龄等这类属性,也有各自的平时要做的事,如讲课、上课、写作业、批改作业等。
类似的,在python里面也定义了类
- 类:具有相同属性和方法的对象的集合。
- 对象:对象就是类的实例。对象有属性和方法
- 方法:就是类中定义的函数
- 属性:包含类属性和实例属性,类属性就是类中所有对象共有的属性,实例属性是实例化对象的属性;同名时实例对象优先调用实例属性
那么在python里面如何定义学生和老师这两类人呢
1,使用class定义一个类名,如下,定义Student(一般首字母大写)类
class Student:
pass
2,实例化,调用定义好的类,类名+()
class Student:
pass
Student()
3,定义类的实例属性,借用魔术方法(以__开头且以__结尾的方法,会自动调用) :
- 构造方法__new__(cls):当实例化的时候,会自动调用__new__(cls)方法,把需要实例化的类对象作为实参传给cls形参,然后__new__再根据该类对象创建一个实例对象。(默认所有类都继承objext类,而object类中有定义了__new__,所以一般在类的定义中不写也是可以的)
- 初始化方法__init__(self):再自动调用__init__(self)方法,把刚创建的实例对象作为实参传递给self形参,然后__init__再对实例对象进行属性初始化,最后再把__new__把属性初始化之后的实例对象返回。(默认所有类都继承objext类,而object类中有定义了__init__,但是没有任何属性初始化,所以在创建类的时候如果要自定义属性还是要重新自己写)
class Student:
#实例属性定义
'''
def __init(self,想定义的属性名1,属性名2...):
self.属性1名称 = 想定义的属性名1 #即表示把传入的实参赋值给self.属性1名称
'''
def __init__(self, name, age, weight): #在self后面加上你想定义的属性名称
self.name = name #把传入的name属性值赋值给对象self.name属性,即完成类的属性定义
self.age = age
self.weight = weight
#实例化的时候注意传入属性对应的值
stu1 = Student('zhangsan', 14, 8)
stu2 = Student('jige', 15, 6)
print(stu1)
print(stu2)
#实例属性调用,通过实例对象去调用,修改也可以这么去改
print(stu1.name)
print(stu2.name)
输出为
<__main__.Student object at 0x000001F54BE22FD0>
<__main__.Student object at 0x000001F54BE22640>
zhangsan
jige
如上例中,即完成了一个含有name、age、weight三个属性的Student类,并且完成了‘zhangsan’和‘jige’的实例化
4,定义类属性 对于类中所有对象共有的属性,需要定义类属性
class Student:
#类属性
school = "翻斗大街中学"
#实例属性
def __init__(self, name, age, weight): #在self后面加上你想定义的属性名称
self.name = name #把传入的name属性值赋值给对象self.name属性,即完成类的属性定义
self.age = age
self.weight = weight
stu1 = Student('zhangsan', 14, 8)
stu2 = Student('jige', 15, 6)
print(stu1)
print(stu2)
## 类属性调用:既可以直接用类的名称去调用,也可以用实例对象去调用;修改只能用类名称去修改
print(Student.school)
print(stu1.school)
print(stu2.school)
输出为
<__main__.Student object at 0x000001F54BE68FA0>
<__main__.Student object at 0x000001F54BE68EE0>
翻斗大街中学
翻斗大街中学
翻斗大街中学
如上例中,对于Student这个类,即定义了一个school类属性
5,定义对象方法
直接在类中定义函数,这个函数就是这个类中所有对象可调用的类方法,传参可以使用self,从而可以使用对象属性
class Student:
#类属性
school = "翻斗大街中学"
#实例属性
def __init__(self, name, age, weight): #在self后面加上你想定义的属性名称
self.name = name #把传入的name属性值赋值给对象self.name属性,即完成类的属性定义
self.age = age
self.weight = weight
#定义功能,传参为self形参,那么就可以使用对象属性
def study(self):
print(f'{self.name}是学生')
print(f'{self.age}是他的年龄')
stu1 = Student('zhangsan', 14, 8)
stu2 = Student('jige', 15, 6)
print(stu1)
print(stu2)
#调用对象方法
stu1.study()
输出为
<__main__.Student object at 0x000001F54BE22F40>
<__main__.Student object at 0x000001F54BE22FD0>
zhangsan是学生
14是他的年龄
6,定义类方法
和对象方法的区别就传入形参需要是类属性,另外要用装饰器@classmethod来声明是定义的类方法
class Student:
#类属性
school = "翻斗大街中学"
#实例属性
def __init__(self, name, age, weight): #在self后面加上你想定义的属性名称
self.name = name #把传入的name属性值赋值给对象self.name属性,即完成类的属性定义
self.age = age
self.weight = weight
#定义类方法
@classmethod
def sleep(cls):
print(f'{cls.school} will sleep')
stu1 = Student('zhangsan', 14, 8)
stu2 = Student('jige', 15, 6)
print(stu1)
print(stu2)
#调用类方法,既可以直接用类名实参,也可以用实例对象
Student.sleep()
输出为
<__main__.Student object at 0x000001F54BE22670>
<__main__.Student object at 0x000001F54BE22D90>
zhangsan是学生
14是他的年龄
翻斗大街中学 will sleep
三,面向对象的三大特性
1,封装
可以在属性或方法前面加两个下划线开头,使其变为私有属性或方法,意思就是只能在类的内部调用,不能在类的外部直接引用,但可以通过非私有方法来进行访问,如下
class Teacher:
def __init__(self, name, age):
self.name = name
self.__age = age #定义age为私有属性
#使用非私有方法访问私有属性
def showAge(self):
print(f'{self.name}有{self.__age}岁了')
tea1 = Teacher('aji',35)
print(tea1.name)
# print(tea1.__age) #执行发现会报错说找不到此属性
tea1.showAge()
输出为
aji
aji有35岁了
2,继承
所有的类都继承object类;子类继承父类后,会拥有父类的非私有属性和方法;在程序的执行中,会先找自己的,再去找父类的
class Teacher:
def __init__(self, name, age):
self.name = name
self.__age = age
def showAge(self):
print(f'{self.name}有{self.__age}岁了')
#使用Tea01继承Teacher
class Tea01(Teacher):
pass
3,多态性
不同对象对同一消息做出不同响应,有多个类继承,并各自声明了同一个方法,那么在调用不同类同一个方法的时候,会执行各自定义的方法逻辑,如下
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
def animal_speak(animal):
print(animal.speak())
dog = Dog()
cat = Cat()
animal_speak(dog) # 输出 "汪汪!"
animal_speak(cat) # 输出 "喵喵!"
在这个例子中,定义了一个父类 Animal 和两个子类 Dog 和 Cat,它们都实现了 speak() 方法。在 animal_speak() 函数中,传入任意一个 Animal 类型的对象,都会调用该对象的 speak() 方法并输出结果。在实例化 Dog 和 Cat 对象后,分别调用了它们的 speak() 方法,输出了不同的声音,这就是多态。