面向对象基础
编程思想
编程思想 - 程序员在遇到问题解决问题的思维模式
-
面向过程编程(穷人思想) - 基本语法,逻辑
-
函数式编程(小资思想) - 掌握函数(遇到问题先想想有没有一个已经存在的函数具备解决这个问题的能力,如果有直接调用,没有就创建一个这样的函数)
-
面向对象编程(富豪思想) - 类、对象(变量、函数)
认识类和对象
什么是类、什么是对象
-
类就是拥有相同功能和相同属性的对象的集合。 - 抽象的概念
-
对象就是类的实例(类具体的表现)
人是类,具体的一个人就是它的对象,比如:余婷、骆昊
电脑是类,我的桌上这台电脑是它的对象
杯子是类,我桌上这个杯子都是它的对象
list是类,[10,20]是列表的对象
类就是类型、类别
创建类
-
定义类(创建类) - 用代码描述清楚这个类是拥有哪些相同功能和相同属性的对象的集合
功能 - 函数
属性 - 保存数据的变量
语法:
class 类名:
类的说明文档
类的内容
说明:
a. class - 关键字:固定写法
b. 类名 - 程序员自己命名
采用驼峰式命名并且首字母大写。(类名大写开头;驼峰式 - 从第二个单词开始首字母大写)
c. : - 固定写法
d. 类的说明文档 - 多行注释
e. 类的内容 - 相同功能和相同属性。
由方法(对象方法、类方法、静态方法)和属性(对象属性、类属性)组成
方法 - 定义在类中的函数
属性 - 定义在类中的变量
class Person:
"""人类"""
num = 61 # num是属性
def eat(self): # eat是方法
print('吃饭')
def sleep(self):
print('睡')
创建对象
语法:
类名() - 创建指定类对应的一个对象,并且将对象返回
p1 = Person()
p2 = Person()
类中的方法
方法 - 定义在类中的函数用来描述具备的功能
类中的方法有三种:对象方法、类方法、静态方法
对象方法
a.怎么定义:将函数直接定义在类中
b.怎么调用:通过对象来调用 - 对象.xxx()
c.特点:自带参数self,通过对象调用对象方法的时候参数self不需要传参,系统自动将当前对象传给self
(self,谁调用就指向谁)
d.什么时候用:如果实现函数的功能需要用到对象属性就使用对象方法
类方法
a.怎么定义:定义函数前加装饰器’@classmethod’
b.怎么调用:通过类来调用 - 类.xxx()
c.特点:自带参数cls,使用时不需要传参,系统自动将当前对象传给cls
d.什么时候用:如果实现函数的功能不需要用到对象属性需要类就是用类方法
静态方法
a.怎么定义:定义函数前加装饰器’@staticmethod’
b.怎么调用:通过类来调用 - 类.xxx()
c.特点:没有特点
d.什么时候用:如果实现函数的功能既不需要对象属性也不需要类属性就使用静态方法
class A:
def func1(self):
print('对象方法')
def func11(self, x, y):
print('对象方法2')
@classmethod
def func2(cls):
print('类方法')
@staticmethod
def func3():
print('静态方法')
a = A()
b = A()
print(f'a:{a}')
# 通过对象调用对象方法
a.func1()
b.func11(200, 200)
a.func11(x=100, y=200)
# 通过类调用类方法
A.func2()
# 通过类调用静态方法
A.func3()
初始化方法
魔法方法:
方法名以’__‘开头并且以’__'结尾的自带的方法,就是魔法。
所有的魔法方法都会特定的情况下被自动调用。
常用的魔法方法:__init__方法、__repr__方法
_repr_
打印对象的时候会自动调用对象对应的类中的__repr__方法,来定制打印规则(函数的返回值是什么,对象打印结果是什么)
返回值必须是字符串!
class A:
def __repr__(self):
return 'abc'
pass
a1 = A()
print(f'a1:{a1}') # a1:abc
b2 = A()
print(f'b2:{b2}') # a2:abc
_init_
每次创建类的对象的时候会自动调用类中的__init__方法
class B:
def __init__(self):
print('init方法')
b1 = B()
b2 = B()
class C:
# 在类中添加__init__方法的时候,除了方法名和方法类型不能动,可以随意添加参数和随意添加函数体
def __init__(self, x, y):
print('C的init方法', x, y)
# 创建类的对象的时候需不需要参数,需要几个参数,由类中__init__方法决定
c1 = C(10, 20)
c2 = C(100, 200)
c3 = C(x = 1, y = 2)
属性
属性
属性分为对象属性和类属性两种
-
类属性
a.怎么创建:在类中定义一个变量,这个变量就是类属性
b.怎么使用:通过类来使用 - 类.xxx
c.什么时候用:当属性值不会因为对象不同而不一样的时候就使用类属性 -
对象属性
a.怎么创建:以’self.属性名=值’的形式定义在类的__init__方法
b.怎么使用:
c.什么时候用:当属性值会因为对象不同而不一样的时候就使用对象属性
class A:
# x是类属性
x = 100
# name和num是对象属性
def __init__(self):
self.name = '小明'
self.num = 10
# 使用类属性
print(A.x) # 100
# 修改类属性的值#
A.x = 200
print(A.x) # 200
a = A()
# 使用对象属性
print(a.name,a.num) # 小明 10
# 修改对象属性的值
a.name = '小花'
a.num = 10
print(a.name,a.num) # 小花 10
练习:定义一个圆的类,拥有属性:半径和圆周率,拥有的方法:求周长和求面积
class Circle:
Pi = 3.14
def __init__(self):
self.R = 1
def get_perimeter(self):
C = 2 * Circle.Pi * self.R
return C
# 类中实现函数功能的时候如果需要的数据是属性,不需要提供额外的参数
def get_area(self):
# self = c1 ; self = c2
# 如果需要类属性直接用类来提供
# 如果需要对象属性用self来提供
S = Circle.Pi * self.R ** 2
return S
c1 = Circle()
c2 = Circle()
c2.R = 3
print(c1.get_perimeter())
print(c1.get_area())
对象属性赋初值的方式
- 通过使用没有默认值的参数来赋值
- 赋固定的值
- 使用由默认值的参数来赋值
class Person:
def __init__(self,name,gender = '男'):
self.name = name # 通过使用没有默认值的参数来赋值
self.age = 1 # 赋固定的值
self.gender = gender # 使用由默认值的参数来赋值
def __repr__(self):
# return f'姓名:{self.name},年龄:{self.age},性别:{self.gender}'
return f'<{str(self.__dict__)[1:-1]}>'
p1 = Person('小明')
print(p1.name,p1.age,p1.gender) # 小明 1 男
p2 = Person('小花','女')
print(p2.name,p2.age,p2.gender) # 小花 1 女
print(p1) # <'name': '小明', 'age': 1, 'gender': '男'>
print(p2) # <'name': '小花', 'age': 1, 'gender': '女'>
练习:创建一个矩形类(根据生活扩展类的内容)
class Rectangle:
def __init__(self,length,width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * (self.length + self.width)
def __repr__(self):
# return f'长度:{self.length},宽度:{self.width}'
return f'<{str(self.__dict__)[1:-1]}>'
r1 = Rectangle(5,4)
r2 = Rectangle(10,7)
print(r1) # <'length': 5, 'width': 4>
print(r2) # <'length': 10, 'width': 7>
属性的增删改查
面向对象编程中可用对象代替字典
在面向对象编程的时候,可以直接使用对象来代替字典
-
用字典
stu1 = {'name': '小明', 'age': 12, 'score': 67} stu2 = {'name': '小花', 'age': 19, 'score': 100}
-
使用对象(先苦后甜,定义一次类,之后都能用)
class Student: def __init__(self, name, age=18, score=0): self.name = name self.age = age self.score = score def __repr__(self): return str(self.__dict__) stu1 = Student('小明', 12, 67) stu2 = Student('小花', 19, 100) print(stu1, stu2) # {'name': '小明', 'age': 12, 'score': 67} {'name': '小花', 'age': 19, 'score': 100}
对象的对象属性支持增删改查
- 查 - 获取属性值
a. 对象.属性 - 获取指定属性的值,属性不存在报错
print(stu1.name)
print(stu1.gender) # 报错!
b. getattr(对象,属性名) - 获取指定属性的值,属性不存在报错
print(getattr(stu1, 'name'))
print(getattr(stu1,'gender')) # 报错
b. getattr(对象,属性名,默认值) - 获取指定属性的值,属性不存在直接返回默认值
print(getattr(stu1, 'gender', '男')) # 男
- 增、改
a. 对象.属性 = 值 - 当属性存在的时候修改指定属性对应的值;当属性不存在的时候给对象添加属性
print(stu1) # {'name': '小明', 'age': 12, 'score': 67}
stu1.age = 22
print(stu1) # {'name': '小明', 'age': 22, 'score': 67}
stu1.gender = '男'
print(stu1) # {'name': '小明', 'age': 22, 'score': 67, 'gender': '男'}
b. setattr(对象,属性,值) - 当属性存在的时候修改指定属性对应的值;当属性不存在的时候给对象添加属性
setattr(stu1,'study_id','001')
print(stu1)
setattr(stu1,'score','76')
print(stu1)
# attr相关函数可以动态操作对象属性
# value = input('请输入你想要查看的属性:')
# print(getattr(stu1,value))
- 删
a. del 对象.属性
print(stu1) # {'name': '小明', 'age': 22, 'score': '76', 'gender': '男', 'study_id': '001'}
del stu1.age
print(stu1) # {'name': '小明', 'score': '76', 'gender': '男', 'study_id': '001'}
b. delattr(对象,属性名)
delattr(stu1,'name')
print(stu1) # {'score': '76', 'gender': '男', 'study_id': '001'}
- 判断属性是否存在
hasattr(对象,属性名)
print(hasattr(stu1,'name')) # False
print(hasattr(stu1,'score')) # True
if not hasattr(stu1, 'name'):
stu1.name = '小明'
继承
继承
继承 - 让子类直接拥有父类的属性和方法
父类就是一个大的类,子类就是这个大的类下面的一个小的分类
继承的语法
class 类名(父类):
类的说明文档
类的内容
注意:定义类的时候如果没有写父类,这个类默认继承object(基类)
class Person: == class(object):
class A:
a = 100
def __init__(self):
self.b = 10
self.c = 20
def func1(self):
print('对象方法')
@classmethod
def func2(cls):
print('类方法')
@staticmethod
def func3():
print('静态方法')
class B(A):
pass
print(B.a) # 100
x = B()
print(x.b, x.c) # 10 20
x.func1() # 对象方法
B.func2() # 类方法
B.func3() # 静态方法
子类添加内容
子类在拥有父类的属性和方法的同时,往往需要有属于自己特有的一些属性和方法
-
添加类属性和方法
直接在子类中定义新的类属性和方法
-
添加对象属性
需要在子类的__init__方法中通过super()去调用父类的__init__方法来继承父类的对象属性
class C(A):
m = 11
def __init__(self):
super().__init__() # 调用当前类的父类的__init__()
self.name = '小明'
def func11(self):
print('C的对象方法')
@classmethod
def func22(cls):
print('C的类方法')
@staticmethod
def func33():
print('C的静态方法')
def func1(self):
print('C的对象方法2')
print(C.a,C.m) # 100 11