一、面向对象思想
1.案例
万物皆对象
在Python中,任何内容都是一个对象
num = 10
案例一:我中午想吃油泼面
面向过程【process,处理】 面向对象
1.买菜,买面 1.委托一个人帮忙买菜,买面
2.收拾 2.委托一个人收拾
3.做饭 3.委托一个会做饭的人做饭
4.吃饭 4.自己吃
案例二:小明是一个电脑小白,组装一台电脑,打游戏
面向过程 面向对象
1.小明补习电脑知识 1.小明委托一个懂电脑的人帮忙买零件
2.小明去买零件 2.小明委托一个快递将零件带回家里
3.小明把零件带回家里 3.小明委托一个动手能力强的人组装零件
4.小明组装电脑 4.小明打游戏
5.小明打游戏
案例三:一辆黑色的宝马在京藏高速上行驶
2.面向过程和面向对象的区别
2.1面向过程
在生活案例中:一种看待问题的方式,在解决问题的时候,侧重与问题是怎样一步一步解决的,然后亲力亲为的去解决
在编程中:
代码从上往下依次执行的
各模块之间的关系尽可能简单,在功能上相对独立
程序的流程在写程序的时候已经确定
程序员扮演的角色:执行者
2.2面向对象
在生活案例中:也是一种看待问题的方式,在解决问题的时候,侧重于找到一个具有特殊功能的实体【个体】,然后委托该个体去帮忙完成某件事情,该个体或者实体被称为对象
在编程中:
对同类对象进行抽取,形成类
类中的大多数数据,只能用本类中的方法处理
类通过一个简单的接口与外界产生联系,对象与对象之间进行通信
程序流程是由用户在使用的过程中决定的
程序员扮演的角色:指挥者
面向对象更符合人类的思想【懒人思想】,可以将复杂的问题简单化
使用面向对象的思想开发,先要找到具有特殊功能的对象,如果该对象不存在,则创建
注意:面向对象是一种思想,并不是一门编程语言
类和对象是面向对象的核心
二、类和对象
1.概念
类:一个具有特殊功能的实体的集合【群体】
对象:在一个类中,一个具有特殊功能的实体,能够帮忙完成某件事情。对象也被称为实例【instance】
两者之间的关系:类用于描述某一类对象的共同特征,而对象则是类的具体的存在【不严谨的说:包含关系】
类是抽象的模板,对象则是具体的存在
问题:先有对象还是先有类?
一般在程序中,都是先定义类,然后通过类创建对象
举例:
类 对象
人类 张三,杨阳。。。。
快递 具体的门店
帮助理解:类也是一种数据类型,只不过是自定义的,跟number,string等类似,通过类创建对象其实就是定义一个该类的变量
2.定义
语法:
class 类名():
类体
说明:
a.Python中使用关键字class定义类
b.类名:只要是一个合法的标识符即可,但是,尽量做到见名知意
要求:遵循大驼峰命名法则【第一单词的首字母大写】
c.():目前是空的,里面主要书写的是当前类的父类,()可以省略
d.通过缩进来区分类体的存在
e.类体一般包含两部分内容:对类的特征描述【名词】,对类的行为描述【动词】
#类的定义:类的声明和类的实现 class MyClass1(): #类的定义相当于函数的定义 pass #注意:在同一个py文件中可以同时定义多个类,但是,为了提高代码的可读性, # 结合模块的使用,一般要求一个py文件中定义一个类 class Myclass2(): pass #注意:如果将多个类定义在同一个文件中,尽量避免重名,类似于函数,后出现的会覆盖掉先出现的
3.设计类
三要素:
事物名称:类名,比如:人 【Person】
特征:属性【变量】,比如:身高,年龄,姓名等-----》名词
行为:函数,比如:跑步,打球等------》动词
初期学习:通过提炼动名词进行类的抽取
三、类中的方法和属性
1.定义
如果只有类单独存在,将没有任何意义,所以,在类中定义成员
换句话说:定义类就是定义类中的成员【成员变量和成员方法】
成员变量:定义在类中的变量,也被称为属性
成员方法:定义在类中的方法,被称为成员函数
只要是拥有相同的属性或者方法的对象都可以抽取成一个类
注意:同一个类中的对象虽然具有相同的属性和行为,但是,属性的数据可能是不一样的
2.使用
2.1实例化对象【创建对象】
创建对象的过程被称为对象的实例化对象的过程
语法:
变量的定义:变量名 = 初始值 num = 10
对象的创建:对象名 = 类名() p = Person()
说明:
a.创建一个对象相当于定义了一个指定类的变量
b.对象名就是一个变量名,被称为引用
c.类名()实质上调用了一个函数,目前默认调用的是无参的函数
d.一个类可以创建无数个对象
2.2对象调用方法和访问属性
如果访问类中的属性或者调用类中的方法,则需要通过对象操作
总结:
a.访问属性和调用函数:对象.xxx
b.根据同一个类创建出来的对象,他们的数据有可能是不同的,相互之间互不影响
#一、定义类【类的设计】 #1.事物的名称: 类名【类的声明】 class Person(): #2.事物的特征:成员变量【属性】【类的实现】 name = "" age = 0 height = 0.0 #3.事物的行为:成员方法【函数】【类的实现】 """ 注意: a.类中的成员方法区别于普通方法:参数部分一定包含self,而且self最好出现在形参列表的第一个 b.调用函数的时候,self本身不需要被传参,系统会自动传参 c.self本质就是一个形参【变量】,只要是一个合法的标识符即可,所以,self可以是任意的标识符 d.self表示自己,代表的是当前类的实例【对象】,结合其他编程语言【java中,self是关键字】,习惯上使用self e.除了上面几点,成员方法和普通方法的用法完全类似,也可以设置默认参数,关键字参数以及不定长参数 """ def run(self): print(id(self)) print("running") def eat(self,food): print("eating",food) #定义类之后,类和函数都会引入新的作用域【在类中定义的变量和函数在类的外部不能直接访问】 # print(name) # run() #普通函数 # def show(): # print("show") #二、对象的创建【实例化对象】 #注意:p1是一个变量名,也被称为引用,在面向对象中,被称为对象, # 实质上并不是一个对象,而是指向了一个真正的对象的引用 #p1被存储在栈中,真正的对象存储在堆中 p1 = Person() print(type(p1)) # num = 10 # s = "hello" # print(type(num),type(s)) print(id(p1)) p2 = Person() print(type(p2)) print(id(p2)) #通过同一个类创建无数个对象,每个对象都是不同的对象【id地址】 num1 = 10 num2 = 10 print(id(num1),id(num2)) #三、属性的访问和方法的调用 #1.访问属性 #语法:对象.属性名 #赋值:对象.属性名 = 值 per = Person() #访问 print(per.name,per.age,per.height) #重新赋值 per.name = "zhangsan" per.age = 18 per.height = 178.0 print(per.name,per.age,per.height) #2.调用函数【方法】 #语法:对象.函数(实参列表) #注意:self不需要传参,其他参数传递的时候需要注意参数的类型【默认参数,关键字参数,不定长参数】 #注意:self默认的值为当前的对象【谁调用成员函数,self代表就是谁】 print(id(per)) per.run() """ per的地址:2213386224976 self的地址:2213386224976 """ per.eat("apple")
2.3内存中的对象
扩展:内存分类
a.寄存器:最快的存储区,由编译器根据需求进行分配,我们在程序中无法控制
b.栈:存放的引用
特点:被执行完成之后,该函数或者变量占用的空间会立即被释放【销毁,release】
c.堆:存放的是所有的对象
特点:执行完之后不会立即被释放,当使用完成之后,会被标上垃圾的标记,等待垃圾回收机制回收它【建议:初始化对象或者一个对象不用的时候,置为None】
d.方法区
静态域:存放静态成员
常量池:存放数字类型和字符串类型的常量
per = Person()
说明:per存储在栈中,per指向了实际的Person对象,Person对象存储在堆中
2.4对象动态绑定属性
Python程序在运行的过程中,可以给某个指定的对象动态的绑定属性
class Myclass(): #属性 num = 0 #方法 def show(self): print("showing") m1 = Myclass() #类属性 print(m1.num) #0 print(id(m1.num)) #实例属性【对象属性】 #此处的num和类=中定义的num不是同一个,原因:是动态绑定的,语法:对象.变量名 = 值 m1.num = 18 print(m1.num) print(id(m1.num)) m1.name = "jack" print(m1.name) m1.show() #注意:给一个对象绑定的属性,其他的对象不能共享 m2 = Myclass() print(m2.num) #0 #print(m2.name) m2.name = "tom" print(m2.name) #总结:在类中定义的属性,通过该类创建的所有的对象都可以访问,但是,动态绑定的属性,只有当前对象可以访问
3.综合案例一
#测试文件【整合】 """ 需求:新学期开学,王老师让小明,小花,小丽做自我介绍 需要介绍姓名,年龄,爱好,并来一段才艺展示 分析: 老师类:Teacher 特征:姓名 name 行为:让xx做自我介绍 letSrudentIntroduce() 学生类:Student 特征:姓名,年龄,爱好 name age hobby 行为:做自我介绍,一段才艺展示 introduce() 分别定义才艺展示的函数 """ #1.导入模块 from practice01.student import Student from practice01.teacher import Teacher #2.创建一个老师对象 wang = Teacher() wang.name = "王老师" #动态绑定,并给属性赋值 #3.创建一个学生对象 xiaoming = Student() xiaoming.name = "小明" xiaoming.age = 19 xiaoming.hobby = "吹牛逼" #4.作为指挥者,指挥对象完成某些操作【让对象执行自己的行为】 wang.letStudentIntroduce(xiaoming) xiaohua = Student() xiaohua.name = "小花" xiaohua.age = 19 xiaohua.hobby = "唱歌" wang.letStudentIntroduce(xiaohua) xiaoli = Student() xiaoli.name = "小丽" xiaoli.age = 19 xiaoli.hobby = "跳舞" wang.letStudentIntroduce(xiaoli)
#实体文件 """ 学生类:Student 特征:姓名,年龄,爱好 name age hobby 行为:做自我介绍,一段才艺展示 introduce() 分别定义才艺展示的函数 """ class Student(): #特征 # name = "" # age = 0 # hobby = "" __slots__ = ("name","age","hobby") #行为 #stu.introduce() self = stu = Stdeunt() def introduce(self): #self代表是当前对象 print("大家好,我是%s,今年%d岁,爱好:%s" % (self.name,self.age,self.hobby)) def dance(self): print(self.name + "跳舞") def sing(self): print(self.name + "唱歌") def lie(self): print(self.name + "吹牛逼")
#实体文件 """ 老师类:Teacher 特征:姓名 name 行为:让xx做自我介绍 letSrudentIntroduce() """ class Teacher(): #特征 #name = "" __slots__ = ("name") #行为 #stu代表的是需要进行自我介绍的学生对象,并不是一个名字的字符串 #wang.letStudentIntroduce(xiaoming) self = Teacher() stu = Stdeunt() def letStudentIntroduce(self,stu): print(self.name + "让" + stu.name + "做自我介绍") #学生执行自己的行为 stu.introduce() if stu.name == "小花": stu.sing() elif stu.name == "小丽": stu.dance() else: stu.lie()
四、构造函数
1.概念
使用直接赋值的方式创建对象,但是,很多类倾向于在创建对象的时候将对象创建为有初始状态的,因此一般情况下,会在类中定义一个名为__init__的函数,该函数被称为构造函数【构造器】 构造函数的作用:创建对象,将对象的数据进行初始化 per = Person() xiaoming = Student() 构造函数调用的时机:当创建对象【实例化对象】的时候第一个被自动调用 语法: def __init__(self,args1,args2...): 函数体 说明: a.之前的写法中并没有显式的定义__init__函数,但是能够创建对象,主要是因为系统默认提供了一个无参的构造函数 b.args1,args2...表示需要初始化的变量,一般和成员变量有关
2.使用
#1.构造函数调用的时机 class Check1(): #成员变量 num1 = 0 s1 = "" #成员方法 def func(self): print("func") #构造函数 def __init__(self): print("构造函数被调用了") #如果在一个类中,同时出现了__init__和__new__,当创建对象的时候优先调用的是new # def __new__(cls, *args, **kwargs): # print("new~~~~~") c1 = Check1() # print(c1.num1) c1.func() c1.func() c1.func() c1.func() c11 = Check1() """ 【面试题1:init和new之间的区别和联系】 a.二者都是在创建对象的过程被自动调用的函数 b.如果init存在,new不存在,则调用的是init,当new和init同时存在,则调用是new 【面试题2:构造函数和普通成员函数之间的区别和联系】 相同点: a.都是函数,都包含声明部分和实现部分 b.形参列表的第一个参数都是self,默认传的是当前的对象 不同点: a.成员函数的函数名可以自定义,但是,构造函数的函数名是固定的,只能是__init__ b.成员函数需要通过对象手动调用,但是,构造函数是在创建对象的过程中自动被调用的 c.对于同一个对象而言,成员函数可以被调用多次,但是,构造函数只能被调用一次 """ #2.给构造函数添加参数 class Check2(): #成员变量 num1 = 0 s1 = "" #成员方法 def func(self): print("func") #构造函数 # def __init__(self,n,s): # print("构造函数被调用了~~~222") # def __init__(self): # print("sjgdhbh") #使用上面的方式;后面的会覆盖掉前面的,则可以用下面的办法解决问题 def __init__(self,*args,**kwargs): print("构造函数被调用了~~~222") c2 = Check2() c21 = Check2(17,"abc") """ a.当在类中显式的定义了构造函数,并给构造函数添加了参数,则系统将不再提供无参的构造函数 则创建对象的时候,类中的构造函数需要什么样的参数,则实参需要保持一致 b。如果想要一个构造函数可以创建出不同形式的对象,则可以在构造函数设置不定长参数 """ #3.构造函数的额作用:给成员变量赋值 class Check3(): #成员变量:类属性【属于类】 num1 = 20 s1 = "aaa" #成员方法 def func(self): print("func") #构造函数 def __init__(self,num1,s1): print("构造函数被调用了~~~333") #实例属性/对象属性【属于对象】 #self的作用:用于区分实例属性和局部变量 self.num1 = num1 self.s1 = s1 c3 = Check3(10,"abc") print(c3.num1) print(c3.s1) #4.在构造函数中定义了实例属性,则类属性可以省略 class Check4(): #成员变量:类属性【属于类】 # num1 = 20 # s1 = "aaa" #成员方法 def func(self): print("func") #构造函数 def __init__(self,num1,s1): print("构造函数被调用了~~~444") #实例属性/对象属性【属于对象】 #self的作用:用于区分实例属性和局部变量 #在构造函手中定义变量,而且通过对象给变量赋值,则该变量被称为实例属性 #构造函数的形参列表和实例属性有关,命名一般和实例属性重名,通过self区分 self.num1 = num1 self.s1 = s1 c4 = Check4(111,"hello") print(c4.num1,c4.s1) #5.书写类的基本模板 class Person(): #构造函数 def __init__(self,name,age): self.name = name self.age = age #成员函数 def eat(self): print("eating") p1 = Person("zhangsan",19) print(p1.name,p1.age) #总结:一般情况下,在一个类中,只需要包含构造函数和成员函数两部分, #在构造函数中,定义成员变量【实例属性】,并给成员变量进行赋值,通过有参的构造函数给成员变量传参
3.综合案例二
""" 需求:富二代王思聪开着豪车玛莎拉蒂,很自豪的向他的新女友炫耀起来 分析: 富二代类:RichMan 特征:有钱,姓名 行为:开车,炫耀 汽车类:Car 特征:品牌,颜色 行为:行驶 女友类:GF 特征:姓名 """ #1.导入类 from practice02.car import Car from practice02.gf import GF from practice02.richman import Richman #2.创建对象 wang = Richman("王思聪") car = Car("五菱宏光","银白色") gf = GF("凤姐") #3.让对象执行自己的行为 wang.drive(car) wang.show(gf,car)
""" 富二代类:RichMan 特征:有钱,姓名 行为:开车,炫耀 """ class Richman(): def __init__(self, name): self.name = name self.hasMoney = True #gf和car都是一个对象 def drive(self,car): #car = car print(self.name + "正在开着他的" + car.brand) car.run() def show(self,gf,car): #gf = gf car = car print(self.name + "向" + gf.name + "炫耀" + car.color + "的" + car.brand)
""" 女友类:GF 特征:姓名 """ class GF(): def __init__(self,name): self.name = name
""" 汽车类:Car 特征:品牌,颜色 行为:行驶 """ class Car(): def __init__(self,brand,color): self.brand = brand self.color = color def run(self): print("running")