面向对象
三大特性: 封装、继承、多态
封装:
- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
继承:
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
多态:
- 传入不同的对象,产生不同的结果
类和对象的关系:用类去创建(实例化)一个对象
类
一系列具有相同特征和行为的事物的统称。
特征:类的属性
行为:类的方法
对象
对象是由类实例化出来的,先有类后有对象
语法:
对象名 = 类名()
self
self 指的事调用函数的对象
class Washer():
def wash(self):
print('洗衣服')
print(self)
washer = Washer()
print(washer) #<__main__.Washer object at 0x014CE580>
washer.wash() #<__main__.Washer object at 0x014CE580>
washers = Washer()
washers.wash() #<__main__.Washer object at 0x015CE130>
添加和获得对象的属性
对象的属性既可以在类外面添加和获取,也能在类里面添加和获取
类外面添加对象属性
语法
对象名.属性名 = 值
class Washer():
def wash(self):
print('洗衣服')
print(self.own)
washer = Washer()
washer.own = 'James'
washer.width = 400
washer.height = 500
print(f'洗衣机宽度是{washer.width}')
print(f'洗衣机高度是{washer.height}')
washer.wash() # 'James'
魔法方法(Magic Methods)
_ _ xx_ _()的函数叫做魔法方法,指的是具有特殊功能的函数
_ _ init _ _()
作用:初始化对象
注意
_ _ init _ _()方法,在创建一个对象时,默认被调用,不需要手动调用
_ _ init _ _(self) 中的self 参数不需要开发者传递,python解释器会自动把当前的对象引用传递过去
class Washer():
def __init__(self):
self.width = 100
self.height = 400
def wash(self):
print(f'洗衣机的高度是{self.height}')
print(f'洗衣机的宽度是{self.width}')
haier = Washer()
haier.wash()
带参数_ _ init _ _()
class Washer():
def __init__(self,width,height):
self.width = width
self.height = height
def wash(self):
print(f'洗衣机的高度是{self.height}')
print(f'洗衣机的宽度是{self.width}')
haier = Washer(10,20)
haier.wash()
_ _ str _ _()
作用:默认情况下,print输出对象,打印的是对象的内存地址。如果类定义了_ _ str _ _()方法,那么就会打印从在这个方法中return 的数据
class Washer():
def __init__(self):
self.width = 100
self.height = 400
def __str__(self):
return '洗衣机说明书'
haier = Washer()
print(haier) #洗衣机说明书
_ _ del _ _()
当删除对象时,python解释器也会默认调用_ _ del _ _()
class Washer():
def __init__(self):
self.width = 100
self.height = 400
def __del__(self):
print('对象已经被删除')
haier = Washer()
# 运行好了,自动执行_ _ del _ _()
继承
class 类名(object): # 小括号内不填,也默认 object # 新式类
代码
Python 面对对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法
class Washer(object):
def __init__(self):
self.width = 100
self.height = 400
def wash(self):
print(f'洗衣机的宽度是{self.width}')
def __del__(self):
print('对象已经被删除')
class Haier(Washer):
pass
result = Haier()
result.wash()
#洗衣机的宽度是100
#对象已经被删除
单继承
只继承一个父类
多继承
同时继承多个父类
注意:父类之间有同名属性和方法,先继承第一个父类中的同名属性和方法
如果父子类有同名属性和方法,调用子类中的同名和方法(重写)
查看类的继承关系
print(类名.__mro__)
**子类调用父类的同名方法和属性 **&& 多层继承
class Master(object):
def __init__(self):
self.kongfu = '师父'
def make_cake(self):
print(f'{self.kongfu}的手艺')
def own_name(self):
print('Master')
class School(object):
def __init__(self):
self.kongfu = '学校'
def make_cake(self):
print(f'{self.kongfu}的手艺')
def school_name(self):
print('school')
class Prentice(Master, School):
def __init__(self):
self.kongfu = '徒弟'
def make_cake(self):
self.__init__() #如果忽略,daqiu.make_cake()输出就是师父的手艺
print(f'{self.kongfu}的手艺')
def master_make_cake(self):
Master.__init__(self) #如果忽略, daqiu.master_make_cake()输出就是徒弟的手艺
Master.make_cake(self)
daqiu = Prentice()
daqiu.master_make_cake() # 师父的手艺
daqiu.make_cake() # 徒弟的手艺
#**多层继承**
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
xiaoqiu.master_make_cake() # 师父的手艺
xiaoqiu.make_cake() # 徒弟的手艺
super()调用父类方法
使用super()可以自动查找父类。调用顺序遵循_ _mro _ _类属性的顺序。适合单继承使用
def make_old_cake1(self):
Master.__init__(self)
Master.make_cake(self)
School.__init__(self)
School.make_cake(self)
def make_old_cake2(self):
super(Prentice, self).__init__()
super(Prentice, self).make_cake()
def make_old_cake3(self):
#简化
super().__init__()
super().make_cake()
daqiu.make_old_cake1() # 师父的手艺,徒弟的手艺
daqiu.make_old_cake2() # 师父的手艺
daqiu.make_old_cake3() # 师父的手艺
私有权限
为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类
设置私有权限的方法:在属性名和方法名 前面加上两个下划线 _ _。
私有属性和私有方法只能在类的里面访问和修改:
定义函数名 get_xx 用来获取私有属性,定义 set_xx 用来修改私有属性 (函数名按照工作习惯定get ,set)
class Prentice(Master, School):
def __init__(self):
self.kongfu = '徒弟'
# 私有属性
self.__money = 2000000
# 私有方法
def __info_print(self):
print(self.__money)
# 获取money私有属性
def get_money(self):
return self.__money()
# 修改money私有属性的值
def set_money(self):
self.__money = 50
多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
- 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化
- 实现步骤:
- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
class Dog(object):
def work(self):
pass
class ArmyDog(Dog):
def work(self):
print('追击敌人')
class DrugDog(Dog):
def work(self):
print('追查毒品')
class Person(object):
def work_with_dog(self, dog):
dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad) #追击敌人
daqiu.work_with_dog(dd) #追查毒品
类属性
优点:
记录的某项数据始终保持一致时,则定义类属性
实例属性 要求每个对象为其单独开辟一份内存空间来记录数据,而类属性为全类所共有,仅占用一份内存,更加节省内存空间
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性
class Dog(object):
tooth = 100
wangcai = Dog()
xiaohei = Dog()
Dog.tooth = 100
print(Dog.tooth) # 100
print(wangcai.tooth) # 100
print(xiaohei.tooth) # 100
wangcai.tooth = 200
print(Dog.tooth) # 100
print(wangcai.tooth) # 200
print(xiaohei.tooth) # 100
类方法和静态方法
类方法
需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数
场景
- 当方法中需要使用类对象(如访问私有类属性等)时,定义类方法
- 类方法一般和类属性配合使用
class Dog(object):
__tooth = 100
@classmethod
def get_tooth(cls):
return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result) # 100
静态方法
特点
- 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
- 静态方法也能通过实例对象和类对象去访问
场景
- 当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性,类方法,创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗
class Dog(object):
@staticmethod
def info_print():
print('这是一个静态方法')
wangcai = Dog()
wangcai.info_print()
Dog.info_print()