目录
1、面向对象与面向过程
面向过程:自顶向下,逐步细化;程序主体是函数
面向对象:尽可能模拟现实世界,使任何一个动作的发生都有一个支配该动作的实体(对象)
每个对象各不相同,都有自己的规律和属性,对象之间可相互联系相互作用
思想:首先想到由什么样的主体实现什么样的功能,再把该主体的属性和功能统一的进行封装,最后才去实现主体的各个功能
不仅仅是简单的将功能进行封装,更是对调用该功能的主体的封装,实现某一主体拥有多个功能
在使用过程中,先得到对应的主体,再使用主体去实现相应的功能
◎都可以实现代码重用和模块化编程,面向对象的模块化更深,数据也更封闭和安全
◎ 面向对象的思维方式更加贴近现实生活,更容易解决大型的复杂的业务逻辑
◎从前期开发的角度来看,面向对象比面向过程要更复杂,但是从维护和扩展的角度来看,面向对象要远比面向过程简单!
◎面向过程的代码执行效率比面向对象高
2、面向对象基本概念
面向对象分析 OOA 面向对象设计 OOD 面向对象编程 OOP
对象的概念:object,现实业务逻辑对应的动作实体
类的概念:class,具有相同或相似属性和动作的一组实体的集合,使用类来产生对象,用类来规定对象的属性和方法
3、类
类的定义与实例化
# 类的定义和使用
# 类名不区分大小写,遵守一般的标识符的命名规则,一般类名的首字母都大写(大驼峰法)
# 定义类 class语句,
# 经典类
class Classname:
'''类的帮助信息'''
statement # 类体
# 新式类
class NClassname(): # 带了小括号,
'''类的帮助信息'''
statement # 类体
class Person(object):
def eat(self):
print('榴莲')
def goal(self):
print('成功')
############################
# class语句本身并不创建该类的任何实例,在定义完成了可以创建类的实例
# 创建类的实例 即实例化该类的对象
# 基本语法: 对象名 = 类名()
p1 = Person()
print(p1) #<__main__.Person object at 0x103878580>
# 调用实例
p1.goal() # 成功
p1.eat() # 榴莲
###
# 一个类可以创建多个对象,但指向的是不同的地址
p1 = Person()
p2 = Person()
类的属性添加
########## 添加和获取对象属性
# 在类的外面添加属性和获取属性
对象名.属性 = 属性值
# 获取
对象名.属性
class Person(object):
pass
p1 = Person()
# 添加属性
p1.name = '张三'
p1.age = '12'
# 获取属性
print(p1.age)
# 在类中使用self.属性可以从内部获取外部定义的属性
class Person(object):
def per(self):
print(f'名字:{self.name}',f'年纪:{self.age}')
p1 = Person()
# 添加属性
p1.name = '张三'
p1.age = '12'
p1.per() # 名字:张三 年纪:12
类属性和实例属性
# 类属性 ---- 定义在类中,并且在函数体外的属性,可以在类的所有实例之间共享信息
class Geese:
'''燕类'''
color = '黑白相间'
# 实例属性 --- 指定义在类的方法中的属性,只作用于当前实例
# 使用 self.属性名
class Geese1:
'''燕类'''
def __init__(self):
self.color = '黑白相间'
4、魔术方法
_ _xx_ _的函数,魔术方法,指的是具有特殊功能的函数
_ _ init _ _( )
## __init__() 初始化方法或构造方法
# 创建类的实例后,会自动执行它,不需要手动调用
# 必须包含一个self参数,并且必须是第一个参数,代表实例化对象的本身
# 通常用来实现对对象的初始化,如赋予相关属性,打开文件等
class Geese:
def __init__(self,color,weiba):
print(color,weiba)
g1 = Geese('黑白','尾巴像剪刀') # 参数会自动传递到__init__里的参数
_ _ del _ _( )
### __del__方法 删除方法或析构方法
# 当删除对象时(调用del删除对象或文件执行结束后),python解释器会默认调用__del__放啊
# 主要用于关闭文件、关闭数据库连接等
class Person():
# 构造__init__
def __init__(self,name,age):
self.name = name
self.age = age
def __del__(self):
print(f'{self}对象已删除')
p1 = Person('张三',24)
print(p1.age,p1.name)
## 手工删除
del p1
_ _ str _ _( )
### __str__
# 当使用print输出对象时,默认打印对象的内存地址,定义str方法,就会打印这个方法中return的数据
# 实例化对象后也会自动执行,返回的必须是字符串类型
class Person():
# 构造__init__
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return f'名字是{self.name},年龄是{self.age}'
p1 = Person('张三',24)
print(p1)
5、面向对象的三大特点
①封装:
将属性和方法写到类中的操作即为封装,封装可以为属性和方法添加私有权限
公有(属性、方法),私有(属性、方法) 控制外部对隐藏的属性的操作行为
# 设置私有属性或方法: 在属性或方法名前加 _ _
# 类中的私有属性和方法,不能被其子类继承
# 对私有属性的访问:(经过权限验证,有权限可以访问)
定义函数get_ _属性名:获取私有属性
定义函数set_ _属性名 :修改私有属性
# 私有方法的封装意义: 降低程序的复杂性
# 私有方法举例
class ATM():
# 加__将方法私有化,方便直接用公共方法全部调用
def __card(self):
print('插卡')
def __input(self):
print('输入取款金额')
# 定义一个对外提供服务的公共方法,
# 使用这个方法就可以直接下列所有私有方法,不需要再一个个调用
def withdraw(self):
self.__card()
self.__input()
atm =ATM()
atm.withdraw()
②继承:
定义:
一个类从另一个已有的类获得其成员的相关特性,继承后必须要有扩展
子类默认继承父类的所有属性和方法,也可以重写(覆盖)父类的属性和方法(扩展)
当子类的成员和继承的父类的成员重名时,子类的成员会覆盖掉父类的成员内容
类中方法的调用顺序:子类会在自己的类寻找某方法,如果找不到才会去父类中寻找,所以重写父类的方法后,父类的方法还是存在的
# # 父类
class Animal(object):
def eat(self):
print('i can eat food')
def call(self):
print('i can call')
# 子类
class Cat(Animal):
# 扩展,和父类重名就会覆盖父类的成员
def call(self):
print('喵喵叫')
class Dog(Animal):
def call(self):
print('汪汪叫')
cat = Cat()
cat.eat()
cat.call()
dog =Dog()
dog.eat()
dog.call()
supper方法和MRO属性
##########
# 强制调用父类的重名属性或方法 supper()
class Cat(Animal):
def call(self):
# supper().属性或方法
super().call()
print('喵喵叫')
##########
# MRO属性(方法):方法解析顺序,了解继承关系
# 属性.__mro__ 或 属性.mro()
print(Cat.__mro__)
#(<class '__main__.Cat'>, <class '__main__.Animal'>, <class 'object'>)
# 派生 :从一个已有的类产生新的类
父类:也叫基类,已有的被继承的类
子类:也叫派生类或扩展类(在子类中增加自己的特性就叫扩展)
单继承:只能继承一个类,会继承父类的所有属性和方法,具有传递性(可以多层继承)
多继承:可以同时继承多个类
③多态
是同一类事物具有的多种不同的形态。不同的对象调用同一方法,表现出不同的状态。
首先要有继承关系,还要编写公共接口(方法),必须有一个参数----->>>以后调用都是通过这个接口,接口内传递的参数必须是一个子类对象
6、类方法 @classmethod
针对类定义的方法,可以访问类中的属性或调用其他类的方法
## 类方法 基本语法
@classmethod # 修饰符/语法糖
def 类方法名称(cls):
pass
# 由哪一个类调用的方法,方法内 cls 就是哪一个类的引用
# cls. 访问类的属性或调用其他类的方法
class Fruit(object):
# 定义类属性——调用次数,初始为0
count = 0
# 定义实例属性
def __init__(self,name):
self.name = name
# 实例化一次调用次数加一
Fruit.count += 1
# 定义类方法,来访问类属性
@classmethod
def fruit_count(cls): # 注意这个名称不要和上面的类属性同名
print(f'这个类{cls}被实例化了{cls.count}次')
# 实例化对象
f1 = Fruit('榴莲')
f2 = Fruit('荔枝')
# 调用类方法
Fruit.fruit_count()
7、静态方法 @staticmethod
既不需要访问实例属性或方法,也不需要访问类属性或方法的方法。比如打印功能菜单信息
既可以通过 类名.方法() 调用,也可以实例化后用 实例对象.方法() 调用
### 静态方法 @staticmethod
class Game(object):
# 打印游戏功能菜单
@staticmethod
def menu():
print('1、开始游戏')
print('2、暂停游戏')
print('3、退出游戏')
Game.menu()