python 完全面向对象_python 面向对象

1:面向对象基础

1:面向对象的基本概念

1:面向过程,(怎么做)

把完成某一个需求的 所有步骤 从头到尾 逐步实现

根据开发需求,将某些 功能独立的代码 封装 成一个函数

最后完成的代码,就顺序的调用 不同的函数

特点:

注重 步骤与过程

开发复杂的项目,没有固定的套路,开发难度很大

2:面向对象(谁来做)

相比较函数,面向对象是更大封装,根据职责 再一个对象中封装多个方法

1:要完成某一需求前,首先确定一下职责,-----要做的事情

2:根据职责 确定不同的对象,对象内部封装不同的 方法(多个)

3:最后完成代码,就是顺序的让不同的对象 调用不同的方法

特点:

1:注重 对象和职责,不同的对象 承担不同的职责

2:对应 复杂项目的开发,提供固定的套路

3:

2:类和对象的基本概念

类和对象 是面向对象的两个核心概念

1:类:

类是对一群 有相同的特征 或者 的事物的一个统称,是抽象的,不能直接使用

特征:被称为属性

行为:被称为方法

类是负责创建对象的

2:对象

对象:是由类创建出来具体存在的,可直接使用的

有哪一个类创建的对象,就拥有哪一类中定义的:

属性

方法

3:类和对象的关系

类是模板,对象是根据类这个模板创建出来的 ,现有类,再有对象

类只有一个,而对象可以多个

类中定义什么 属性和方法,对象就有什么对象和方法,不可能多,也不可能少

3:设计类的三要素和名词提炼法

1:在程序开发中,要设计一个类,满足一下三个要素

1):类名:这类事物的名字,满足大驼峰命名法

2):属性:这类事物有什么杨的特征

3):方法:这类事物有什么样的行为

大驼峰命名法:

1):每一个单词的首字母大写

2:): 单词和单词之间没有下划线

2:类名的确定

名词提炼法:分析整个业务流程,出现名词,就是要找的类

3:属性和方法的确定

对 对象的特征描述, 通常可以定义成属性

对象具体有的行为(动词),通常可以定成方法

4:内置的dir函数查询对象的方法列表

变量,数据,函数,都会对象

在python中使用两种方法验证

1:在标识符数据 后输入一个 . 然后tab ,ipython会提示调用的方法列表

2:使用内置函数,dir 传入 标识符/数据,可以查看对象内的所有属性和方法

5:定义简单的类01_基本语法

1:python中定义只包含方法的类

class类名:def方法1(self,参数列表):pass

def方法2(self,参数列表):pass

第一个参数必须是self ,类名的命名规则符合大驼峰命名法

2:当一个类定义完成之后,要使用这个类创建对象

对象的变量名=类名()

6:定义简单的类02_案例演练

1:第一个面向对象的程序

需求:小猫爱吃鱼,小猫要喝水

分析:定义一个 猫类,定义两个方法eat和drink ,按需求,不需要定义属性

classCat:defeat(self):print("小猫爱吃鱼")defdrink(self,):print("小猫要喝水")#创建对象

tom =Cat()

tom.eat()

tom.drink()

7:定义简单的类03_接受对象变量的同时是对对象的引用

classCat:defeat(self):print("小猫爱吃鱼")defdrink(self,):print("小猫要喝水")#创建对象

tom =Cat()"""tom变量记录的是对象在内存中的地址,

也就是Tom 变量应用新建毛的对象

利用print函数输出Tom变量,是能够输出这个变量应用的对象 是有一个类创建的对象,以及内存中的地址"""tom.eat()

tom.drink()print(tom)#<__main__.Cat object at 0x0000025595BECD30>

8:定义简单的类_04 创建多个猫对象

classCat:defeat(self):print("小猫爱吃鱼")defdrink(self,):print("小猫要喝水")#创建对象

tom =Cat()"""tom变量记录的是对象在内存中的地址,

也就是Tom 变量应用新建毛的对象

利用print函数输出Tom变量,是能够输出这个变量应用的对象 是有一个类创建的对象,以及内存中的地址"""tom.eat()

tom.drink()print(tom)#<__main__.Cat object at 0x0000025595BECD30>#创建多个猫对象,他们不是一个猫对象

lazy_cat=Cat()

lazy_cat.drink()

lazy_cat.eat()print(lazy_cat)#<__main__.Cat object at 0x00000249FF46CE48>

9:-self-01 在类的外部给对象添加属性

1:给类的对象设置属性,非常容易,但不推荐使用

#创建对象

tom =Cat()

tom.name="Tom"#创建多个猫对象,他们不是一个猫对象

lazy_cat=Cat()

lazy_cat.name="大懒猫"

10:self-02 利用self在类的封装的方法中输出多个属性

classCat:#有哪一个对象调用的方法,方法内的 self 就是哪一个对象的引用

defeat(self):print("%s爱吃鱼" %self.name)defdrink(self,):print("%s要喝水"%self.name)#创建对象

tom =Cat()

tom.name="Tom"tom.eat()

tom.drink()#创建多个猫对象,他们不是一个猫对象

lazy_cat=Cat()

lazy_cat.name="大懒猫"lazy_cat.drink()

lazy_cat.eat()

11:初始化方法-01-在类的外部给对象添加属性的隐患

先调用方法,在设置属性

classCat:defeat(self):print("%s爱吃鱼" %self.name)defdrink(self,):print("%s要喝水"%self.name)#创建对象

tom =Cat()

tom.eat()

tom.drink()

tom.name="Tom"

报错

AttributeError: 'Cat' object has no attribute 'name'

提示:对象包含哪些属性,应该封装在类的内部

12:初始化方法-02-创建对象时自动调用初始化方法

当用类名创建对象时,会自动执行以下操作

1:为对象在内存中分配空间——创建对象

2:为对象的属性 设置初始值——初始化方法(init)

这个初始化方法就是_init_方法,是对象的内置方法,专门定义一个类 具有哪些属性方法!

classCat:def __init__(self):print("这是一个初始化方法")

tom=Cat()#使用类名创建对象的时候,会自动调用初始化方法_init_

这是一个初始化方法

13:初始化方法-03-初始化方法中定义属性

在_init_方法内部使用 self.属性名=属性的初始值 ,就可以定义属性

定义属性之后,在使用Cat创建对象,都会有该属性

classCat:def __init__(self):print("这是一个初始化方法")

self.name="tom"

defeat(self):print("%s爱吃鱼" %self.name)

tom=Cat()

tom.eat()

print(tom.name)#打印Tom的属性

14初始化方法-04-使用参数设置属性的初始值

在开发的过程中,如果希望 创建对象的同时,就设置对象的属性,可以对init方法进行改造

1:把希望设置的属性值,定义成_init_ 方法参数

2:在方法内部使用 self.属性=形参 接受外界传递的参数

3:在创建对象时,使用 类名(属性1,属性2……)调用

classCat:def __init__(self,new_name):print("这是一个初始化方法")#self.name="tom"

self.name=new_namedefeat(self):print("%s爱吃鱼" %self.name)

tom=Cat("tom")

tom.eat()

lazy_cat=Cat("大懒猫")

lazy_cat.eat()

15:-内置方法-01- del的方法和对象的生命周期

当一个对象从内存中销毁前,会自动调用_del_方法

classCat:def __init__(self,new_name):

self.name=new_nameprint("%s 来了"%self.name)def __del__(self):print("%s去了" %self.name)#tom是一个全局变量

tom=Cat("tom")print("-" *50)

tom 来了

--------------------------------------------------

tom去了

classCat:def __init__(self,new_name):

self.name=new_nameprint("%s 来了"%self.name)def __del__(self):print("%s去了" %self.name)#tom是一个全局变量

tom=Cat("tom")#del 关键字可以删除一个对象

deltomprint("-" *50)

tom 来了

tom去了

--------------------------------------------------

16:内置方法-02- str- 方法定制变量的输出信息

在python中使用print输出对象变量,默认情况下,会输出这个变量 引用的对象 是 有哪一个类创建的,以及内存中的地址

在开发中,希望使用 print 输出 对象变量时,能够打印自定义的内容,就可以使用_str_内置方法了

注意:_str_方法必须返回一个字符串

classCat:def __init__(self,new_name):

self.name=new_nameprint("%s 来了"%self.name)def __del__(self):print("%s去了" %self.name)def __str__(self):return "我是一只小猫【%s】"%self.name#tom是一个全局变量

tom=Cat("tom")print(tom)#del 关键字可以删除一个对象

deltomprint("-" *50)

tom 来了

我是一只小猫【tom】

tom去了

--------------------------------------------------

2:面向对象练习

1:小明爱跑步

1):封装

封装面向对象的一大特点,

面向对象的第一步--将属性和方法 封装到一个抽象的类中

外界使用类创建对象,然后让对象去调用方法

对象方法的细节都被封装在类的内部

2):小明爱跑步

1:小明的体重 75.0 公斤

2:小明每次跑步会减肥 0.5公斤

3:小明每次吃东西 增加 1 公斤

classPerson:def __init__(self,name,weight):

self.name=name

self.weight=weightdef __str__(self):return "我是%s,我的体重是%.2f 公斤"%(self.name,self.weight)defeat(self):print("%s是吃货,吃完东西在减肥"%self.name)

self.weight+=1.0

defrun(self):

self.weight-=0.5xiaoming=Person("xiaoming",75.0)

xiaoming.eat()

xiaoming.run()print(xiaoming)

3):提示:在对象的内部,是可以直接访问对象的属性的

同一个类中的 多个对象之间,属性互不干扰

classPerson:def __init__(self,name,weight):

self.name=name

self.weight=weightdef __str__(self):return "我是%s,我的体重是%.2f 公斤"%(self.name,self.weight)defeat(self):print("%s是吃货,吃完东西在减肥"%self.name)

self.weight+=1.0

defrun(self):

self.weight-=0.5xiaoming=Person("xiaoming",75.0)

xiaoming.eat()

xiaoming.run()print(xiaoming)

xiaomei=Person("xiaomei",55.0)

xiaomei.run()

xiaomei.eat()print(xiaomei)

2:摆放家具

需求

1:房子(house)有户型,总面积 和家具名称列表

新房子没有任何的家具

2:家具(HOuseItem)有名字 和占地面积,其中

席梦思(bed):4平米

衣柜(chest):2平米

餐桌(table):1.5平米

4:打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表

HouseItem

naem

area

_init_(self,name,are)

_str_(self)

House

house_type

area

free_area

item_list

_init_(self,house_type,are)

_str_(self)

add_item(self,item)

剩余面积

创建房子对象时,定义一个剩余面积的属性,初始值和总面积相等

当调用 add_item 方法时,向房间添加家具时 剩余面积-=家具面积

家具类

classHouseItem:def __init__(self,name,area):

self.name=name

self.area=areadef __str__(self):return ("[%s]:\t%.2f 平米"%(self.name,self.area))

bed=HouseItem("席梦思",4)

chest=HouseItem("衣柜",2)

table=HouseItem("餐桌",1.5)print(bed)print(chest)print(table)

房子类

classHouse:def __init__(self,house_type,area):

self.house_type=house_type

self.area=area#剩余面积

self.free_area=area#家具名臣列表

self.item_list=[]def __str__(self):#python 能够自动将一对括号的代码连接在一起

return ("户型:%s \n总面积:%.2f[剩余面积:%.2f]\n家具:%s"

%(self.house_type,self.area,

self.free_area,self.item_list ))defadd_item(self,item):print("要添加%s"%item)#self.item_list.append(item)

my_house=House("两室一厅",60)print(my_house)

小结:让房子类调用三次 add_item,准备添加家具

添加家具

classHouseItem:def __init__(self,name,area):

self.name=name

self.area=areadef __str__(self):return ("[%s:]%.2f 平米"%(self.name,self.area))classHouse:def __init__(self,house_type,area):

self.house_type=house_type

self.area=area#剩余面积

self.free_area=area#家具名臣列表

self.item_list=[]def __str__(self):#python 能够自动将一对括号的代码连接在一起

return ("户型:%s \n总面积:%.2f[剩余面积:%.2f]\n家具:%s"

%(self.house_type,self.area,

self.free_area,self.item_list ))defadd_item(self,item):print("要添加%s"%item)#判断家具面积

if item.area>self.free_area:print("%s面积太大了,无法添加"%(item.name))return

#将加剧名臣添加到列表

self.item_list.append(item.name)#计算剩余面积

self.free_area-=item.area

bed=HouseItem("席梦思",4)

chest=HouseItem("衣柜",2)

table=HouseItem("餐桌",1.5)

创建房子对象

my_house=House("两室一厅",60)

my_house.add_item(bed)

my_house.add_item(chest)

my_house.add_item(table)print(my_house)

3:封装案例

1):封装

封装封装面向对象的一大特点,

面向对象的第一步--将属性和方法 封装到一个抽象的类中

外界使用类创建对象,然后让对象去调用属性方法

对象方法的细节都被封装在类的内部

一个对象的 属性 是另一个类创建的 对象

01:士兵突击

需求:

1:士兵 许三多 有一把 AK47

2:士兵可以开火

3:抢能够发射子弹

4:抢装填子弹--增加子弹数量

分析:

类1: 士兵; 属性:名字,抢。 方法:开火

类2: 强; 属性:名字,子弹 方法:发射子弹

写抢类:

classGun:def __init__(self,model):#定义抢的型号

self.model=model#抢子弹的数量

self.bullet_count =0defadd_bullet(self,count):

self.bullet_count+=countdefshoot(self):pass

#判断子弹是否有子弹

if self.bullet_count<=0:print("[%s] 没有子弹...."%self.model)#发射子弹 -1

self.bullet_count-=1

#提示发射

print("[%s] 突突突...[%d]"%(self.model,self.bullet_count))

ak47=Gun("ak47")

ak47.add_bullet(50)

ak47.shoot()

写士兵类

classGun:def __init__(self,model):#定义抢的型号

self.model=model#抢子弹的数量

self.bullet_count =0defadd_bullet(self,count):

self.bullet_count+=countdefshoot(self):pass

#判断子弹是否有子弹

if self.bullet_count<=0:print("[%s] 没有子弹...."%self.model)#发射子弹 -1

self.bullet_count-=1

#提示发射

print("[%s] 突突突...[%d]"%(self.model,self.bullet_count))classSoldier:def __init__(self,name):#姓名

self.name=name#假设每一个士兵开始都没有抢

self.gun=Nonedeffire(self):#判断是否有抢

if self.gun isNone:print("[%s] 还没有抢...."%self.name)return

#高喊口号

print("冲啊...[%s]"%self.name)#让强装填子弹

self.gun.add_bullet(50)#发射子弹

self.gun.shoot()#1:创建抢的对象

ak47=Gun("ak47")#2:给抢装子弹#ak47.add_bullet(50)#3:发射#ak47.shoot()#1:创建士兵的对象

xusanduo=Soldier("许三多")#2:给许三多给一把枪(赋值的形式)一个对象的 属性 是另一个类创建的 对象

xusanduo.gun=ak47#3;开枪

xusanduo.fire()#print(ak47)

身份运算符

身份运算符用于比较 内存的地址 是否一致--是否是对同一对象的引用

在python 中针对None 比较时,建议用 is 判断

is 与 == 区别

is 是判断两个变量 引用的对象是否是同一个

== 用于判断 应用的变量的值是否是同一个

4:私有属性和方法

1:应用场景及定义方式

实际开发中, 对象 的某些属性或方法 可能希望 在对象的内部使用, 而不希望在外部访问到

2:定义方式

在定义属性和方法时 ,在属性或方法的名前 增加 两个下划线 定义的就是私有属性 或方法

classWomen:def __init__(self,name):

self.name=name

self.__age=18

def __secret(self):#在对象的内部可以直接访问对象的私有属性

print("%s 的年龄是 %d"%(self.name,self.__age))

xiaomei=Women("小美")#私有属性,在外界不能直接访问

#print(xiaomei.__age)

xiaomei.__secret

3:伪私有属性和方法

在前面加上 _类名

#print(xiaomei.__age)

xiaomei._Women__secret

3:单继承和方法的重写

面向对象的三大特性

1:封装: 根据职责 将属性和方法 封装到一个抽象的类中

2:继承:是代码的重用

3:多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

单继承

概念:子类拥有父类的所有方法和属性

语法:

class类名(父类名):pass

子类继承父类,可以直接享受父类中以封装好的方法,不需要再次开发

子类 根据职责, 封装子类特有的 属性和方法

专业的术语:

父类===基类

子类===派生类

继承的传递性:

子类拥有 父类 以及 父类的父类 中的所有属性和方法

方法的重写

应用场景:当父类方法的实现 满足不了子类的需求,可以对方法进行 重写

重写 父类的方法 的两种情况

覆盖父类的方法

对父类方法进行扩展

1:覆盖父类的方法(父类方法的实现和子类完全不同)

classAnimal:defeat(self):print("吃....")defdrink(self):print("喝....")defrun(self):print("跑...")classDog(Animal):defbark(self):print("汪汪叫...")classXioaTianQuan(Dog):deffly(self):print("还会飞...")defbark(self):print("叫的跟神一样")

xtq=XioaTianQuan()#如果子类中重写了父类的方法#子类调用对象时,会调用子类中重写的方法

xtq.bark()

2:对父类方法进行扩展(父类的方法是子类的一部分)

采用 super(). 的形式,调用父类方法的执行

关于super()

python 中super是一个特殊的类

super()是super创建的

使用场景, 重写父类方法时,调用父类中封装的方法

classAnimal:defeat(self):print("吃....")defdrink(self):print("喝....")defrun(self):print("跑...")classDog(Animal):defbark(self):print("汪汪叫...")classXioaTianQuan(Dog):deffly(self):print("还会飞...")defbark(self):#针对子类的需求编写代码

print("叫的跟神一样")#使用super(). 调用父类中封装的方法

super().bark()#编写其他代码

xtq=XioaTianQuan()

xtq.bark()

4:私有方法和属性

classA:def __init__(self):

self.num1=100self.__num2=200

def __test(self):print("私有方法 %d %d"%(self.num1,self.__num2))classB(A):passb=B()print(b)#在外界不能直接访问对象的私有属性调用对象的私有方法

print(b.__num2)#AttributeError: 'B' object has no attribute '__num2'

b._teat()

1:子类对象 不能直接 在自己的方法内部,直接访问 父类的私有属性 或私有 方法

classA:def __init__(self):

self.num1=100self.__num2=200

deftest(self):print("父类的公有方法 %d"%self.__num2)classB(A):defdemo(self):#在子类的对象方法中,不能直接访问父类的私有属性

print("访问父类的私有属性 %d" % self.__num2)#在子类的对象方法中,不能直接访问父类的私有方法

self.__test()

b=B()print(b)#在外界不能直接访问对象的私有属性调用对象的私有方法

print(b.__num2)#AttributeError: 'B' object has no attribute '__num2'

b._teat()

2:子类对象 可以通过父类的 共有方法 间接访问 私有属性或私有方法

classA:def __init__(self):

self.num1=100self.__num2=200

deftest(self):print("父类的公有方法 %d"%self.__num2)

self.__test()def __test(self):print("私有方法 %d %d"%(self.num1,self.__num2))classB(A):defdemo(self):#在子类的对象方法中,通过直接访问父类的公有属性来访问类的私有属性

print("访问父类的私有属性 %d" %self.num1)#在子类的对象方法中,通过直接访问父类的公有方法来访问父类的私有方法

self.test()

b=B()print(b)

b.demo()

5: 多继承

概念

子类 可以拥有 多个父类,并且具有 所有父类的属性和方法

语法

class子类名(父类1,父类2):pass

注意事项

如果父类间存在同名的属性和方法,应该尽量避免

python中的MRO,主要用于多继承时 判断方法,属性的调用路劲

print(C._mrc_)

python 3.0 中所有类的基类是object

6:多态

面向对象的三大特性

1:封装: 根据职责 将属性和方法 封装到一个抽象的类中

2:继承:是代码的重用

3:多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

增加代码的灵活度

以继承和重写父类方法为前提

是调用方法的技巧,不会影响内部的设计

多态案列演练

需求

1:在dog类中封装game方法(普通狗简繁玩耍)

2:定义 xiaotianquan继承 dog 并重写 game 方法(哮天犬上天完)

3:定义person类, 并且封装一个和狗完的方法

方法内部直接让 狗对象调用 game 方法

classDog:def __init__(self,name):

self.name=namedefgame(self):print("%s 蹦蹦跳跳的玩耍..."%self.name)classXiaoTianQuan(Dog):defgame(self):print("%s 飞上天..."%self.name)classProson:def __init__(self,name):

self.name=namedefgame_with_dog(self,dog):print("%s 和 %s 快乐的玩耍..."%(self.name,dog.name))#让狗玩耍

dog.game()#创建狗对象

wangcai=Dog("旺财")#创建一个小明对象

xiaoming =Proson("小明")#让小明调用和狗完的方法

xiaoming.game_with_dog(wangcai)

案例小结:

person类中只需让狗对象,调用game方法,而不关心具体是什么狗

在程序执行时,传入不同的狗对象实参,就会产生不同的结果

7:类属性,类方法,静态方法

1.1术语——实例

1:现象对象开发中,第一步,设计类

2:使用类名创建对象,创建对象的动作有两部:

在内存中分配对象

调用初始化方法 __init__为对象初始化

3:对象创建之后,内存中就有一对象实实在在的存在,-----实例

因此:通常把

创建出来的对象就做类的实例

创建对象的动作叫做实例化

对象的属性叫做实例属性

对象的方法叫做实例方法

在程序执行时:

对象各自拥有自己的实例属性

调用对象的方法,可以通过self.的方式访问自己的属性和自己的方法

结论:

每一个对象都有自己独立的内训空间,保存个不同的属性

多个对象的方法,在内存只有一份,在调用方法时需要把对象引用 传递到方法内部

1.2:类属性

1:类是一个特殊的对象

python中一切皆对象

class A: 属于类对象

a=A() 属于实例对象

在程序运行时,类同样会被加载到内存中

在python中,类是一个特殊的对象,--类对象

在程序运行时,类对象在内存中只有一份,使用一个类可以创建出很多的类实例

除了封装实例的属性和方法外,类对象还可以创建拥有自己的属性和方法

类属性和类方法

通过类名.的方式,可以方法类属性和类方法

2:概念和使用

类属性 就是给 类对象中 定义的 属性

通常会记录与这个类相关的特性

类属性不会记录 具体对象的特征

在class 关键字下方,利用赋值语句来定义

实例需求

定义一个工具类

每件工具都有自己的名字name

需求 --知道这个类创建了多少个工具对象

classTools:#使用赋值语句定义类属性,记录所有工具的数量

count=0def __init__(self,name):

self.name=name#让属性值加1

Tools.count+=1

#创建工具对象

tool1=Tools("斧头")

tool2=Tools("榔头")#输出工具对象的总数

print(Tools.count)

3:属性的获取机制——向上的查找机制

访问属性的两种方式

类名.类属性

对象.类属性(不推荐)

注意:

如果使用对象.类属性=值 ,只会给对象添加一个属性,而不会影响到类属性的值

classTools:#使用赋值语句定义类属性,记录所有工具的数量

count=0def __init__(self,name):

self.name=name#让属性值加1

Tools.count+=1

#创建工具对象

tool1=Tools("斧头")

tool2=Tools("榔头")

tool3=Tools("水桶")#给雷属性进行赋值

tool3.count=99

print(tool3.count)#输出工具对象的总数

print(Tools.count)

1.3:类方法

类方法是针对类对象定义的方法

在类方法内部,可以直接访问类属性,或者调用替他方法

语法如下;

@classmethoddef类方法名(cls):pass

通过类名. 调用类方法调用类方法时,不需要传递cls 参数

在方法内部:

可以通过 cls. 访问类的属性

也可以通过 cls. 调用替他类方法

实例需求

定义一个工具类

每件工具都有自己的名字name

需求 --再类中封装一个 show_tools_count 的类方法,输出使用当前这个类创建的的对象个数

classTools:#使用赋值语句定义类属性,记录所有工具的数量

count=0def __init__(self,name):

self.name=name#让属性值加1

Tools.count+=1@classmethoddefshow_tool_count(cls):#在类方法的内部,可以通过cls.的方式访问类属性

print(Tools.count)#创建工具对象

tool1=Tools("斧头")

tool2=Tools("榔头")

tool3=Tools("水桶")#调用类方法

Tools.show_tool_count()

1.4:静态方法

开发场景:既不需要访问实例属性或调用实例方法,也不需要访问类属性或者调用类方法

@staticmethoddef静态方法名():pass

通过 类名. 的方式来调用

classDog:

@staticmethoddefrun():print("小狗会跑")

Dog.run()

1.5:方法综合案例分析

需求

1:设计一个 game 类

2:属性

定义一个类属性top_score 记录游戏的最高分

定义一个实例属性 play_name 记录当前玩家姓名

3:方法:

静态方法show_help 显示游戏的帮助信息

类方法 show_top_score 显示历史最高分

实例方法 start_game 开始当前的玩家游戏

4:程序步骤

查看帮助信息

查看历史最高分

创建游戏对象

classGame:#类属性:历史最高分

top_score=0#实例属性

def __init__(self,play_name):

self.play_name=play_name

@staticmethoddefshow_help():print("帮助信息:让僵尸进入大门")

@classmethoddefshow_top_score(cls):print(Game.top_score)defstart_game(self):print("开始游戏了 %s"%self.play_name)#查看帮助信息

Game.show_help()#查看历史最高分

Game.show_top_score()#创建游戏对象

game=Game("小明")

game.start_game()

案例小结:

1:实例方法

2:类方法

3:静态方法

8:单例模式

01:单例设计模式

目的:

让类创建对象,在系统中只有唯一的一个实例

每一次执行 类名(),返回的对象,内存地址是相同的

02:__new__方法

1:使用类名()创建对象时,python解释器 首先会 调用__new__方法,分配内存空间

2;__new__是一个object 基类提供的 内置静态方法,主要作用有两个:

在内存中为对象 分配空间

返回对象的引用

3:python解释器获得对象的引用后,将引用作为第一个参数,传递给__init__ f方法

重写 __new__ 方法非常固定

重写__new__方法一定要 return super().__new__(cls)

否则python解释器 得不到 分配空间的对象引用,就不会 调 用对象的初始化方法,就会返回一个 None

注意:__new__是一个静态方法,在调用时 需要传递cls参数

classMusicPlay:def __new__(cls, *args, **kwargs):#创建对象时,new方法会自动调用

print("创建对象,分配空间")#为对象分配空间

instance =super().__new__(cls)#返回对象引用

returninstance

play=MusicPlay()print(play)

03:python中的单例

单例:让类创建的对象,在系统中只有唯一的一个实例

定义一个类属性,初始值NOne,用于记录单例对象的引用

重写new方法

如果 类属性 is None ,调用父类,分配空间,,并在类属性中记录结果

回 类属性 中记录的对象引用

classMusicPlay:#记录一个被创建的对象引用‘

instance=Nonedef __new__(cls, *args, **kwargs):#判断类属性属性是否是空对象

if cls.instance isNone:#调用父类方法,为第一个对象分配空间

cls.instance=super().__new__(cls)#返回类属性对象保存的对象引用

returncls.instance

play1=MusicPlay()print(play1)

play2=MusicPlay()print(play2)

只执行一次初始化工作

使用类名()创建对象时,python解释器自动两个方法

__new__ 分配空间

__init__对象初始化

需求:只执行一次初始化方法

classMusicPlay:#记录一个被创建的对象引用‘

instance=None#记录是否执行初始化工作

init_flag=Falsedef __new__(cls, *args, **kwargs):#判断类属性属性是否是空对象

if cls.instance isNone:#调用父类方法,为第一个对象分配空间

cls.instance=super().__new__(cls)#返回类属性对象保存的对象引用

returncls.instancedef __init__(self):#判断是否执行初始化工作

ifMusicPlay.init_flag:return

#如果没有执行过,在此执行初始化动作

print("初始化播放器")#修改类属性的标记

MusicPlay.init_flag=True

play1=MusicPlay()print(play1)

play2=MusicPlay()print(play2)

9: 异常

01:异常的概念

程序运行时,如果PYthon解释器 遇到一个错误,会停止程序的执行,并且提示一些错误的信息,这既是异常

程序停止执行,并且提示错误信息,这个动作,我们称为抛出异常

程序开发时,不可能将所有的特殊情况处理的面面俱到,通过异常捕获可以针对突发事件做处理,从而保证程序的稳定性和健壮性

02:捕获异常

简单的捕获语法

try:

尝试执行代码except:

出现错误的处理

案例:要求用户输入整数

try:

num=int(input("请输入一个整数:"))except:print("请输入正确的整数")print("-" *50)

03:错误类型的捕获

在程序执行时,可能会遇到不同类型的异常,并且需要针对不同类型的异常,做出不同的相应,就需要捕获错误类型

当python 解释器 抛出异常时,最后一行错误信息的第一个单词你是错误类型

案例-要求用户输入整数

需求:

1:提示用户输入一个整数

2;使用 8 除以输入的整数 并且输出

try:

num=int(input("请输入一个正数:"))

result=8 /numprint(result)exceptZeroDivisionError:print("除数不能为0")exceptValueError:print("你输入的是非法的数字,请重新输入")

04:捕获位置错误

在程序开发时,要预测到所有可能的错误,还是有一定的难度的

如果希望程序无论出现任何错误,都可以抛出

try:

num=int(input("请输入一个正数:"))

result=8 /numprint(result)exceptZeroDivisionError:print("除数不能为0")exceptException as a : #把错误交给变量a,最后输出print("未知错误 %s" % a)

05:异常捕获的完整语法

else : 只有在没有异常的时候才执行的代码

finally: 无论是否有异常,都会执行的代码

try:

num=int(input("请输入一个正数:"))

result=8 /numprint(result)exceptZeroDivisionError:print("除数不能为0")exceptException as a :print("未知错误 %s" %a)else:print("尝试成功")finally:print("无论是否出现错误都会执行的代码")print("-" * 50)

06:异常的传递性

被调用的函数会把异常传给调用方,最后会交给主控程序处理,因此,在主控程序处理异常即可;

defdemo():return int(input("请输入一个整数:"))defdemo2():returndemo()#利用异常的传递性,在主程序铺货异常

try:print(demo2())exceptException as a:print("未知错误:%s"%a)

07;抛出raise 异常

应用场景:

在开发中,除了代码执行出错以外,还可以根据应用程序 特有的业务需求, 主动抛出异常

示例:

提示用户输入密码,如果长度小于8, 抛出异常

抛出异常:

python中提供了一个 Exception 异常类

在开发时,满足特定的业务需求,希望抛出异常类

创建Exception 的对象

使用raise 关键字抛出异常

definput_passwd():#提示用户输入信息

num=input("请输入密码:")#判断密码长度是否>=8,是,返回密码

if len(num)>=8:returnnum#<8,主动抛出异常

print("主动抛出异常")#1)创建异常对象

ex=Exception("密码长度不够")#2)主动抛出异常

raiseextry:print(input_passwd())exceptException as a :print(a)

10:模块和包

01:模块

1.1 模块的概念

模块是python架构的一个核心概念

每一个扩展名 .py 结尾的python源文件都是一个模块

模块名 同样是一个标识符,需要符合标识符的命名规则

在模块定义的全局变量 ,函数,类 都是提供给外界可用的工具

模块好比 工具包,想要使用这个工具包中的工具,就必须先导入这个模块

1.2:模块导入的两种方法

1)import 模块

在导入模块时,每个导入应该独占一行

import模块1import 模块2

通过调用就可用里面的工具

importxpq_01importxpq_02

xpq_01.say_hello()

xpq_02.say_hello()

dog=xpq_01.Dog()print(dog)

cat=xpq_02.Cat()print(cat)

使用as指定模块的别名

importxpq_01 as DogModulimportxpq_02 as CatMOdul

DogModul.say_hello()

CatMOdul.say_hello()

dog=DogModul.Dog()print(dog)

cat=CatMOdul.Cat()print(cat)

2):from......import

从某一个工具中,导入部分工具。

from 模块名 import 工具名

导入之后,可以直接使用 模块的工具---全局变量,函数,类

注意:如果两个模块,存才同名的函数,那么 后倒入的模块,会覆盖先导入的模块

开发时,import 代码 应该统一写在代码的顶部,一旦发现冲突,可以使用as 关键字 给其中的一个工具起一个别名

1.3 模块的搜索顺序

搜索当前目录 模块名文件,如果有,就直接导入,如果没有,就搜索系统目录

模块有一个内置的属性,__file__可以查看模块的完整路径

importxpq_01 as DogModulimportxpq_02 as CatMOdulprint(DogModul.__file__)#D:\PycharmProjects\模块\xpq_01.py

DogModul.say_hello()

CatMOdul.say_hello()

dog=DogModul.Dog()print(dog)

cat=CatMOdul.Cat()print(cat)

1.4:原则--每一个文件都应是可以被导入的

导入文件时,文件中没有任何缩进的代码,都会被执行一遍

实际开发场景

开发人员通常会在 模块下方 增加一些测试代码,仅在模块内使用,仅在模块内使用,而在其他文件中不需要执行

__name__属性

__name__属性可以做到, 测试模块的代码 只在测试的模块中运行,而在被导入时不会被执行

__name__是python中的一个内置属性,记录这一个字符串,

如果是被其他文件导入的,__name__就是模块名

如果是当前执行的程序 __name__是__main__

__name__模块

defsay_hello():print("你好你好,我是 say_hello")#如果直接执行模块,__main__

if __name__=="__main__":print (__name__)#文件被导入时,能够被执行的代码不被执行

print ("小明开发的模块")

say_hello()

__name__导入模块

import __name__模块

print ("-" *50)

很多python文件中看到以下格式代码

#导入模块#定义变量‘’#定义类#定义函数#在代码的最下方

defmain()#。。。

pass

#根据__name__判断,是否执行下方代码

if __name__=="__main__":

main()

02:包

概念:

包是一个包含多个模块的 特殊目录

目录下有一个特殊文件__init__

包名的命名方式和变量一致

好处

使用import 包名 可以一次性的导入包中的所有模块

哟使用 包 中的模块,需要 __init__.py 中指定 对外界提供中的模块列表

#从当权目录 导入 模块列表

from . importsend_messagefrom . import receive_message

11:文件操作

12:文本编码

13:内建函数eval

14:反射

#反射 : 是用字符串类型的名字 去操作 变量#反射是对象中的属性和方法 # hasattr getattr setattr delattr

classA:deffunc(self):print('in func')

a=A()

a.name='alex'a.age=63

#反射的对象属性

ret=getattr(a,'name')#a 对象名, ‘name’属性名

print(ret )#alex#反射方法属性

a.func()

ret= getattr(a,'func')

ret()

反射类的属性和方法

classA:

price= 20@classmethoddeffunc(cls):print('in func')#反射类的属性

A.priceprint(getattr(A,'price'))#20

## 反射类的方法 :classmethod staticmethod

A.func()if hasattr(A,'func'):

getattr(A,'func')#in func

模块中的属性和方法

#模块#import my#反射模块的属性#print(my.day)#print(getattr(my,'day'))

#反射模块的方法#getattr(my,'wahaha')()

#内置模块也能用#time#asctime

importtimeprint(getattr(time,'time')())print(getattr(time,'asctime')())

importsysprint(sys.modules['__main__'])## 反射自己模块中的变量#print(getattr(sys.modules['__main__'],'year'))#

## 反射自己模块中的函数

getattr(sys.modules['__main__'],'qqxing')()

变量名= input('>>>')print(getattr(sys.modules[__name__],变量名))#要反射的函数有参数怎么办?#print(time.strftime('%Y-%m-%d %H:%M:S'))#print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))

#一个模块中的类能不能反射得到#import my#print(getattr(my,'C')())#if hasattr(my,'name'):#getattr(my,'name')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值