面向过程
一. 面向过程(一种编程思想)
过程:解决问题的步骤,目的是将一个复杂的问题拆分成若干小问题,按步骤解决,将问题流程化。
优点:复杂问题简单化
缺点:由于实现流程固定,一旦中间某个步骤发生了修改,导致整体需要修改(如果增加新功能,需要全部修改)
扩展性差,维护性差
应用场景:不需要扩展的程序,如cmd, 记事本,操作系统内核,脚本程序
不适应场景:扩展性高的程序,如QQ.
面向对象
一. 面向对象(oop: object oriented pargramming)
是一种编程思想,即编写代码的方式
实际是找一堆对象,让他们完成任务
将程序看做一堆对象的集合,实现功能的方式就是通过对象间的交互来实现
1. 对象: 具备某些特征与技能的结合体,是实实在在存在的物体
2. 类: 是一个抽象的概念,不是实际存在的,是根据一些具备相同特征和技能的对象抽取得到的
类与对象的关系:类包含了一系列相同特征和技能的对象,对象是属于某个类的实例
类和对象的先后关系: 先有对象,根据对象的特征和技能得到一个类型
程序中:先有类,通过类产生对象。先确定类具备什么特征和行为才能产生对象
3.面向对象优点:不用考虑繁琐的实现步骤
扩展性高,当需要一个新功能时,搞一个具备新功能的对象,命令该对象去完成任务
对象与整体实现流程的耦合度低(当一个对象出现问题,其他对象无影响)
可维护性高
4.面向对象缺点:面向对象的复杂性比面向 过程高
无法预测执行结果
5. 使用场景: 需要较高扩展性的程序(例如直接与用户发生交互的程序)
因为程序与用户打交道,用户需求千变万化,对扩展性要求高
6. 定义类: 大驼峰(首字母全部大写), 在类中描述对象的特征和行为
class Person: ====> 定义Person类
name='egon' ======> 用变量来描述特征
gender='women' 创建对象: 申请内存地址,将对象内容放进去
age=20 name, gender, age 声明在类中,每个对象使用都是一样的内容
obj1 = Person() =====> 调用类(实例化,创建对象)
print( obj ) ===> <__main__.Person object at 0x00000000021DE518> 在类Person 下生成一个对象,内存地址为 0x00000000021DE518
使用对象的属性(用对象名加点访问): obj.name obj.gender obj.age
定制属性: obj1.name = 'alex' print( obj1.name) ====> alex
存放属性的位置:(共同特征)放在类 中
独有特征(如姓名)放在对象中
obj.__dict__获取对象中包含的内容 print(obj1.__dict__) ====> {'name': 'alex'}
Person.__dict__ 获得类中包含的内容 ===》
{'__module__': '__main__', 'name': 'ego', 'gender': 'women', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
类自带一些属性,从父类中得到的
属性的访问顺序: 对象 ===> 类
当对象中存在属性,优先访问对象中的属性,当对象不存在时,在类中找
类: 可以总结为 === > 对象的模板(类如果相同, 具备类中的公共内容)
初始化函数: 简化为每个对象设置值,定义一个函数,用于为对象设置属性
# 初始化函数( 为对象初始化自己独有的特征)
class Student:
school='oldboy'
def set_sttr(obj,name,sex,age):
obj.name=name
obj.sex=sex
obj.age=age
stu1= Student() # 调用类,实例化
Student.set_sttr( stu1, 'egon', 'women', 17 )
set_sttr 这个函数的目的在于设置对象的属性,如果没有对象,则该函数没有意义,因此初始化函数和类应该是一个整体
上述方法缺点: 对象的创建和初始化分开
解决方法: 带有__开头_结尾的函数,特殊的内置函数,会自动触发执行
class Person:
country = 'China'
def __init__(obj,x,y,z):
obj.name = x
obj.age = y
obj.sex = z
def run(self):
print('---->', self)
obj1=Person('egon', 18, 'male') # obj1 相当于__init__函数中的obj
print(obj1) ----> <__main__.People object at 0x0000000001EB6048> 创建了一个对象
print(obj1.run) --> <bound method People.run of <__main__.People object at 0x0000000001E5EF98>>
绑定方法,本质是People类中的run函数,把这个函数绑给了内存地址
obj1.run == People.run(obj1) -----> <__main__.People object at 0x0000000002236048>
print(People.run) ---> <function People.run at 0x000000000239F268> 就是一个函数
__init__函数在调用类时候自动执行
总结: 将对象的创建和初始化合并,简化操作
__init__方法 : 该方法内可以有任意的python代码
一定不能有返回值
类定义中的函数分成两大类:
什么是绑定: 在没学习类之前,数据和调用数据的函数时分离的,每次调用函数都要传入一堆参数
绑定就是将数据与操作数据的函数绑定到一起
如何绑定: 对象
绑定方法:(绑定给谁,谁来调用就自动将他本身(stu1)当做第一个参数传入)
1. 绑定给对象的方法: 默认
为对象量身定制
对象.boud_method() 自动将对象当做第一个参数传入
#绑定给对象的方法:
class Student:
school = 'beijing'
def __init__(self,name,age):
self.name = name
self.age = age
def sayhi(self):
print(' hello my name is %s, my age is %s' %(name,age))
stu1 = Student('egon',18) 创建对象,和初始化(为对象设置属性) 此后可以获得 stu1.name 或 stu1.age
stu1.sayhi() 用对象来调用类中方法,把对象传入 --- 》 hello my name is egon my age:18
Student.sayhi(stu1) 用类名来调用,手动传入对象
总结: 只要拿到了对象,就同时拿到了数据和处理方法!!
# 绑定给类的方法
class Student:
school = 'beijing'
def __init__(self, name, age):
self.name = name
self.age = age
@classmethon 装饰器classmethod 声明绑定给类
# 有一个参数,该参数表示当前类 cls
def print_school( cls): 输出类里面school的属性
print(cls.school)
注意 : 类的绑定方法,对象和类都能调用,并且都会自动传入这个类
Student.print_school() # 类调用,不需要手动传参,自动传入 cls
stu1 = Student('egon', 18) # 对象调用要先创建对象和初始化
stu1.print_school() # 通过对象来调用,无需手动传参,自动传入cls
判断一个方法(类中的函数)到底应该绑定给对象还是类 ???
当处理的数据包含在类中,就绑定给类
当处理的数据包含在对象中,就绑定给对象
总结:1. 为什么绑定:传递参数,必须手动传递,还要注意传参顺序
每次处理数据,都需要手动传参
当处理的数据特别多,列表存放变量,当每次处理,都需先获取数据,在传递给函数
绑定为了简化代码,提高效率
2. 类的绑定方法和对象的绑定方法的相同和不同点:
相同: 都会自动传值
都可以被类和对象调用
不同点:对象绑定方法在 对象调用时,传的是对象自己,而类绑定方法传的是类自己
第一个参数,对象叫self , 类叫cls
非绑定方法:
在类中,既不绑定给类,也不绑定给对象
特点: 没有自动传参数的效果,类和对象都能调用,就是一个普通函数
使用场景: 当功能不需要访问类的数据,也不需要访问对象的数据
# 非绑定方法
class Teacher():
def __init__(self,name,age):
self.name = name
self.age = age
@staticmethod 声明定义非绑定方法
def test_func(num):
print('test_func run!') # 既没有用到类的数据,也没用到对象的数据
print(num)
# 调用
类调用: Teacher.test_func(1)
对象调用: test1 = Teacher('egon',18)
test1.test_func(1)
绑定方法总结:
绑定: 是将数据和类下面定义的函数绑定
绑定方法: 绑定给类(默认): 调用方法:通过类调用 和 通过 对象调用
绑定给对象(@classmethod 声明): 调用方法: 通过类调用和对象调用(自动传参)
非绑定方法:既不绑给类,也不绑给对象,调用方法: 通过类调用和通过对象调用
所有函数的调用都可以通过类调用和对象调用
通过对象调用时: 第一步 要创建对象和初始化 , 第二步调用(注意: 当绑定给对象时,通过对象调用要手动传参)