一、面程和面向对象的区别。
1.面向过程:
就是自顶向下,逐步细化,从开始到结束按照步骤一步一步进行,更加侧重在过程上。
2.面向对象:
面向对象并不是一种技术,而是一种思想,是一种解决问题的最基本的思维方式,使用
面向对象方式就是尽可能地模拟现实世界。
二、面向对象中两个重要的概念 类 和 对象。
1.类:对现实事物的抽象描述。
对象:对现实事物的具体描述。
两者关系:必须先
#定义类
class 类名(object):
#定义方法
方法列表
方法列表处可编辑 属性 和 方法。
举个例子(定义一个汽车类,并拥有跑起来的行为)
#定义汽车类
class Car():
#定义跑起来的方法
def run(self):
print('汽车跑起来了')
当有了类之后,然后根据类才能创建对象,举个例子:
定义手机类
class phone(object):
# 定义打开手机方法
def open(self):
print('打开手机')
# 定义关闭手机方法
def close(self):
print('关闭手机')
# 定义拍照功能
def paizhao(self):
print('拍下一张照片')
# 定义对象手机
sj = phone()
sj.open()
print('-' * 20)
sj.paizhao()
print('-' * 20)
sj.close()
2.self关键字
self也是Python内置的关键字之一,其指向了类实例对象本身,类中的self就是谁实例化了对
象,其就指向谁。
# 1、定义一个类
class Person():
# 定义一个方法
def speak(self):
print(self)
print('Nice to meet you!')
# 2、类的实例化(生成对象)
p1 = Person()
print(p1)
p1.speak()
3.属性
在Python中,任何一个对象都应该由两部分组成:属性 + 方法,所以获取属性也至关重要。
①在类外获取属性
# 对象名.属性 = 属性值
# 1、定义一个Person类
class Person(object):
pass
# 2、实例化Person类,生成p1对象
p1 = Person()
# 3、为p1对象添加属性
p1.name = '老王'
p1.age = 18
②在类内获取属性
# 1、定义一个Person类
class Person():
def speak(self):
print(f'我的名字:{self.name},我的年龄:{self.age}')
# 2、实例化Person类,生成p1对象
p1 = Person()
# 3、添加属性
p1.name = '孙悟空'
p1.age = 500
# 4、调用方法
p1.speak()
三、魔法方法。
通过 对象.属性 的方式设置或获取对象的属性,这种设置属性的方式有点繁琐,每次定义一个
对象,就必须手工为其设置属性,因此我们采用魔术方法来优化。格式为 __方法名__() ,注意前后
均为双下划线。常用方法如下:
1. __init__() 方法
初始化方法或者称之为“构造函数”,在对象初始化时执行,其主要作用就是在对象初始化时,
对对象进行初始化操作(如赋予属性)。
__init__()方法添加的实例属性,会在创建对象的时候自动执行,即__init__()方法,在创建一
个对象时默认被调用,不需要手动调用,,__init__(self)中的self参数,不需要开发者传递,
python解释器会自动把当前的对象引用传递过去。
# 1、定义一个类
class Person():
# 初始化实例对象属性
def __init__(self, name, age):
# 赋予name属性、age属性给实例化对象本身
# self.实例化对象属性 = 参数
self.name = name
self.age = age
# 2、实例化对象并传入初始化属性值
p1 = Person('孙悟空', 500)
# 3、调用p1对象自身属性name与age
print(p1.name)
print(p1.age)
2. __str__() 方法
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__()
方法,那么
就会打印从在这个方法中 return 的数据。(要特别注意__str__()方法返回"字符串类型"的数据)
这个魔术方法是在类的外部,使用print(对象)时,自动被调用的,在类的内部定义__str__
方法时,
必须使用return返回一个字符串类型的数据。
# 1、定义一个类
class Car():
# 首先定义一个__init__方法,用于初始化实例对象属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
# 定义一个__str__内置魔术方法,用于输出小汽车的相关信息
def __str__(self):
return f'汽车品牌:{self.brand},汽车型号:{self.model},汽车颜色:{self.color}'
# 2、实例化对象c1
c1 = Car('奔驰', 'S600', '黑色')
print(c1)
3. __del__() 方法
删除方法或者称之为“析构方法”。当删除对象时(调用del删除对象或者文件执行结束后),
python解释器会自动调用__del__()
方法。
class Person():
# 构造函数__init__
def __init__(self, name, age):
self.name = name
self.age = age
# 析构方法__del__
def __del__(self):
print(f'{self}对象已经被删除')
# 实例化对象
p1 = Person('白骨精', 100)
# 删除对象p1
del p1
四、面向对象的三大特性。
面向对象的三大特性为:封装、继承、多态。
1.封装
含义:把现实世界中的主体中的属性和方法书写到类的里面的操作即为封装;封装可以为属
性和方法添加为私有权限,不能直接被外部访问。
这时就要对私有属性和私有方法有所认识。
设置私有属性和私有方法的方式非常简单:在属性名和方法名前面加上两个下划线即可。
①私有属性和私有方法的格式与运用
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18
xiaomei = Girl('小美')
print(xiaomei.name)
print(xiaomei.__age) # 报错,提示Girl对象没有__age属性
外部可以通过特定的"接口"来实现对私有属性的方法。接口就是我们通常说的一个函数,这个
函数可以实现对某些属性的访问(设置与获取)。
在Python中,一般定义函数名' get_xx '用来获取私有属性,定义' set_xx '用来修改私有属性值。
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18
# 公共方法:提供给外部的访问接口
def get_age(self):
# 内部访问:允许直接访问
# 外部访问:根据需求要添加限制条件
return self.__age
# 公共方法:提供给外部的设置接口
def set_age(self, age):
self.__age = age
girl = Girl('小美')
girl.set_age(19)
print(girl.get_age())
②封装的意义
第一、封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作行为(过滤掉异常数据)。
第二、私有方法封装的意义:降低程序的复杂度。
class ATM():
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入取款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
# 定义一个对外提供服务的公共方法
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
atm = ATM()
atm.withdraw()
2.继承
①概念
继承:一个类从另一个已有的类获得其成员的相关特性,就叫作继承!
派生:从一个已有的类产生一个新的类,称为派生!
父类:也叫作基类,就是指已有被继承的类!
子类:也叫作派生类或扩展类
在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
②单继承和多继承
单继承:一个类只能继承自一个其他的类,不能继承多个类,这个类会有具有父类的属性和
方法,单继承也是大多数面向对象语言的特性!
# 父类B
class B(object):
pass
# 子类A
class A(B):
pass
重写:重写也叫作覆盖,就是当子类成员与父类成员名字相同的时候,从父类继承下来的成
员会重新定义!
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def study(self):
print(f'{self.name}活到老学到老')
class Student(person):
def study(self):
print(f'{self.name}学生发誓好好学习')
class Teacher(person):
def study(self):
print(f'{self.name}老师好好备课')
s1 = Student('张三',20)
t1 = Teacher('李四',20)
s1.study()
t1.study()
扩展:在子类中增加一些自己特有的特性,就叫作扩展,没有扩展,继承也就没有意义了!
也可以添加父类中的属性和方法。格式:super().父类方法() 或者 父类名.父类方法 这两种方法调
用。
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def study(self):
print(f'{self.name}活到老学到老')
def mianshi(self):
print('面试要求着装得体,文明礼貌')
class Student(person):
def study(self):
print(f'{self.name}学生发誓好好学习')
def mianshi(self):
super().mianshi()
print(f'{self.name}要参加面试,好好表现')
class Teacher(person):
def study(self):
print(f'{self.name}老师好好备课')
def mianshi(self):
person.mianshi(self)
print(f'{self.name}要面试同学')
s1 = Student('张三',20)
t1 = Teacher('李四',20)
print(s1.name)
print(t1.age)
s1.study()
t1.study()
print('-' * 20 )
s1.mianshi()
t1.mianshi()
多继承:一个类同时继承了多个父类,(C++、Python等语言都支持多继承)。
注意:多继承中使用 super().父类方法() 时,只能继承第一个父类的该方法,如果需要调用多
个父类的方法时,必须使用 父类名.父类方法 该方法。
通过 子类名.mro() 或者 子类名.__mro__ 来获取继承关系。
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
class Father(Person):
def teach(self):
print('通过打来教育')
class Mother(Person):
def teach(self):
print('通过爱来教育')
class children(Father, Mother):
def teach(self):
Father.teach(self)
Mother.teach(self)
print('通过奖励教育')
c = children('张三', 20)
c.teach()
print(children.mro())
print(children.__mro__)
3.多态
①定义
多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以
产生不同的执行结果。Python中的多态就是指 => 同一个函数,随着传入子类对象的不同,可以实
现不同的功能!
②步骤
第一、有继承。 第二、有函数重写。 第三、父类引用指向子类对象。(但由于python是伪多
态,所以也可以不基于继承)
class Animal(object):
def calls(self):
print('动物会叫')
class Dog(Animal):
def calls(self):
print('狗汪汪叫')
class Cat(Animal):
def calls(self):
print('猫喵喵叫')
class Car():
def calls(self):
print('滴滴')
class Person(object):
def animal_call(self,ani:Animal):
if isinstance(ani,Animal):
ani.calls()
else:
print('类型错误')
p = Person()
p.animal_call(Dog())
p.animal_call(Cat())
p.animal_call(Car())
③多态的优点
在不改变框架代码的情况下,通过多态语法轻松的实现模块和模块之间的解耦合;实现了软
件系统的可拓展。
五、面向对象的其他特性
1.类属性
类属性,指的就是类所拥有的属性,它被共享于整个类中(即都可以直接调用)。
推荐使用:类名.类属性名
class Student(object):
Count = 0
def __init__(self,name,age):
self.name = name
self.age = age
Student.Count += 1
print(f'访问类属性{Student.Count}')
s1 = Student('张三',18)
print(f'访问类属性{s1.Count}')
print(f'访问类属性{Student.Count}')
s2 = Student('李四',19)
print(f'访问类属性{s2.Count}')
print(f'访问类属性{Student.Count}')
s3 = Student('王五',20)
print(f'访问类属性{s3.Count}')
Student.Count += 10
print(f'访问类属性{Student.Count}')
2.类方法
类方法就是针对类对象定义的方法,在类方法中可以直接访问类属性或者调用其他类方法。
类方法需要用修饰器" @classmethod "来标识,告诉解释器这是一个类方法类方法的第一个参
数应该是" cls " ① 有哪一个类调用的方法,方法内的" cls "就是哪一个类的引用 ② 这个参数和示例
方法的第一个参数是"self"类似 ③ 提示使用其他名称也可以,不过习惯使用" cls " 通过类名.调用类
方法,调用方法时,不需要传递" cls "参数。
在方法内部 ① 可以通过"cls."访问类的属性 ② 也可以通过 "cls." 调用其他的类方法
class Student(object):
# 类属性
Count = 0
# 实例属性
def __init__(self, name):
self.name = name
# 实例方法
def study(self):
print(f'{self.name}好好学习,天天向上')
# TODO 类方法 使用装饰器@classmethod修饰,一般都是配合类属性使用
@classmethod
def get_count(cls):
cls.Count = 10
print(cls.Count)
3.静态方法
静态方法需要用修饰器 "@staticmethod" 来标识,告诉解释器这是一个静态方法。
在开发时,如果需要在类中封装一个方法,这个方法:
① 既不需要访问实例属性或者调用实例方法 ;
② 也不需要访问类属性或者调用类方法这个时候,可以把这个方法封装成一个静态方法。
class Game(object):
# 定义静态方法
@staticmethod
def show():
print('欢迎来到xx游戏...')
print('开始按1')
print('暂停按2')
print('结束按3')
# 调用静态方法 方式1(推荐): 类名.类方法名() 方式2: 对象或者self也能调用
Game.show()