类和对象
类是对一系列具有相同特征(属性)和行为(方法)的事务的统称,是一个抽象的概念,对象是类的实例化
定义类
-
语法
class 类名(): 代码 ...
遵循大驼峰命名习惯
创建对象
- 语法:
对象名 = 类名()
类里面的self
self指的是调用该函数的对象
在类的外面添加和获取对象属性
添加
- 对象名.属性名 = 值
- haier1.width = 500
获取
- 对象名.属性名
- print(f’haier1洗衣机的宽度是{haier1.width}’)
属性不存在会报错
类的里面添加和获取对象属性
获取
- self.属性名
魔法方法
在python中,xx()的函数叫做魔法方法,指的是具有特殊功能的函数
init()
初始化对象,设置实例化对象前的属性,类似java的成员变量
注意:
init()方法,在创建一个对象的时候默认被调用,不需要手动调用
init(self)中的self参数,不需要开发者传递,oython解释器会自动把当前的对象的引用传过去
带参数的init方法
类似Java里的有参构造方法,写了之后,创建对象的时候需要传入参数,没传就会报错
str()
类型Java的toString(),未定义时,打印对象的时候,默认打印对象的内存地址。
如果类定义了_str_方法,那么就会打印从在这个方法中return的数据
del()
当删除对象时,python解释器默认调用_del_()方法。程序结束后,会默认调用el方法
案例
烤地瓜
要求
代码
# 1. 定义类:初始化属性。被烤和添加调料的方法,显示对象的str
class SweeetPotato():
def __init__(self):
# 焙烤时间
self.cook_time = 0
# 焙烤状态
self.state = '生的'
# 调料列表
self.condiments = []
def __str__(self):
return f'地瓜的焙烤时间是{self.cook_time},状态是{self.state},添加的调料有{self.condiments}'
def cook(self, time):
""""烤地瓜的方法"""
# 1. 先计算地瓜整体焙烤的时间
self.cook_time += time
# 2. 用整体焙烤的时间再判断地瓜的状态
if 0 <= self.cook_time < 3:
self.state = '生的'
elif 3 <= self.cook_time < 5:
self.state = '半生不熟的'
elif 5 <= self.cook_time < 8:
self.state = '熟的'
else:
self.state='糊的'
def add_condiments(self, condiments):
self.condiments.append(condiments)
# 2. 创建对象并调用对应的实例方法
digua1 = SweeetPotato()
print(digua1)
digua1.cook(2)
digua1.add_condiments('辣椒面')
print(digua1)
digua1.cook(3)
digua1.add_condiments('酱油')
print(digua1)
搬家具
要求
代码
class Furniture():
def __init__(self, name, area):
self.name = name
self.area = area
class Home():
def __init__(self, ardess, area):
self.ardess = ardess
self.area = area
self.free_area = area
self.funitures = []
def __str__(self):
return '房子的住址是{0},占地面积为{1},' \
'剩余面积为{3},家具列表为{2}'.format(self.ardess, self.area, self.funitures, self.free_area)
def add_funiture(self, item):
if item.area <= self.free_area:
self.free_area -= item.area
self.funitures.append(item.name)
else:
print('房子剩余空间过小!')
bed = Furniture('双人床',12)
sofa = Furniture('沙发', 10)
ball = Furniture('篮球场', 1000)
home = Home('中国', 1000)
home.add_funiture(bed)
print(home)
home.add_funiture(sofa)
print(home)
home.add_funiture(ball)
print(home)
拓展
python的2.0版本用经典类;不由任意内置类型派生出的类,称之为经典类。
python的3.0版本用新式类;class 类名(object):小括号里填要继承的父类,默认为object
继承
语法
class 类名(要继承的类名):
object 是所有类的父类,默认都继承object
单继承
就是普通的继承
多继承
一个同时继承多个父类
语法
class 类名(第一个父类,第二个父类)
若一个类有多个父类时,默认使用第一个父类的同名属性和方法
重写
使用对象的方法或属性时,会先调用自己的方法和属性,若自己没有,就会调用父类的,跟Java一样
所以重写的语法:就是在子类里面重新写一遍一样名字的属性和方法
子类和父类具有同名属性和方法时,默认使用子类的同名属性和方法
拓展方法:mro
可以得到当前类的直接父类和直接父类继承的父类
语法:类名.mro:必须用类名调用,而不是对象调用
子类调用父类的同名的方法和属性
自己写独有的方法时,必须先要调用自己的初始化方法
定义一个方法,在方法里初始化父类的初始化方法,然后用父类(类名)调用它的同名方法
self代表当前对象,调用父类方法时,若不使用父类的初始化方法,就会使用子类自己的初始化方法,当前对象的属性就会变成子类的初始化属性,若调用了父类的初始化方法就会把self对象的初始化属性变为父类的初始化属性。
若不调用初始化方法,self对象的属性就不会变,默认优先调用子类的初始化方法
多层继承
爷爷---------父亲-------------儿子
跟Java一样,按照普通继承的想就对
super()调用父类方法
原始的方法,代码的量过大,修改不易,如果父类的名字修改了,代码也该修改
有参:super(当前类名,self).函数()
代码量并未减少多少,但会简单了点
无参:super().函数()
super只能找到直接父类,在多层继承中尤能体现!
私有权限
私有的不会继承给子类
定义私有属性和方法
语法
设置私有权限的方法:在属性名和方法名前面加上两个下划线(__)。
获取和修改私有属性
私有属性和私有方法只能在里面访问和修改
get_xx和set_xx:和Java里的用法一样
利用父类里的公共方法来修改父类的私有属性值
总结
面向对象
三大特性
封装,继承,多态
多态
类属性和实例属性
设置和访问类属性
类属性就是类对象所拥有的属性,它被类的所有实例对象所共有。
类属性可以使用类对象或实例对象访问
相当于Java里的static变量
语法:不在初始化init函数里,直接在类里面写属性
优点
- 记录的某项数据始终保持一致,就定义类属性,因为实例属性需要创建对象,每一个对象都占一份内存,他们的属性也占一份内存
修改类属性
只能用类来修改类属性,不能用对象修改类属性,防止乱修改
如果用类对象去修改,就是创建了一个跟类属性同名的实例属性
类方法和静态方法
类方法的使用
需要用装饰器@classmethod来标识其为类方法,对于类方法,对于类方法,第一个参数就必须是类对象,一般用cls作为第一个参数
Java里的静态方法