链接:python基础(上篇).
链接: python基础(进阶篇)+实战游戏项目.
python基础(下篇)
python 中的函数基础
#h函数定义:
#def + 关键字 +小括号 + 冒号 + 换行缩进+代码块 定义一个函数
# def 函数名():
# 代码块
# def printInfo_wangYu():
# '''
# 这个函数是用来打印隔个人信息的
# :return:
# '''
# print('王钰的身高是%f米'%1.60)
# print('王钰的体重是%fKg'%52.1)
# print('王钰的爱好是%s'%'放屁')
# print('王钰的职业是%s'%'学生')
# pass
# printInfo_wangYu()
# 带参数的
def printInfo_wangYu(name,age,height,hobby,career):
print('{}的身高是{}'.format(name,height))
print('{}的年龄是{}'.format(name,age))
print('{}的爱好是{}'.format(name,hobby))
print('{}的职业是{}'.format(name,career))
pass
printInfo_wangYu('王钰','14','160','放屁','学生')
函数参数
# 参数的分类:
# 必选参数、默认参数[缺省参数]、可选参数、关键字参数
#1.必选参数
def sum(a,b):#形式参数:只是意义上的一种参数,在定义的时候是不占内存地址的
sum=a+b
print(sum)
pass
#函数调用
sum(20,15)#20 15 是实际参数,简称实参 实实在在的占用内存地址的参数
# sum()不能这样写
#两个参数必须都要有的(必选参数)
#2.默认参数[缺省参数]
def sum1(a=20,b=30):
print('默认参数使用=%d'%(a+b))
pass
#默认参数调用
sum1()
def sum2(a,b=40):
print('默认参数使用=%d'%(a+b))
pass
sum2(30)
# def sum3(a=30,b):
# print('默认参数使用=%d'%(a+b))
# pass
# sum3()报错
# sum3(20)error also
# sum3(,40)语法不允许
#所以呢,默认参数一般放在其他参数的前面
#可变参数 (当参数的个数不确定时使用,比较灵活)
def getComputer(*args):
'''
计算累加和
:param args:可变长的参数类型
:return:
'''
# print(args)
result=0
for item in args:
result+=item
pass
print('result=%d'%result)
pass
getComputer(1,2,3,4,5,6)
#关键字可变参数
# ** 来定义
# 在函数体内 参数关键字是一个字典类型 key是一个字符串
def keyFunc(**kwargs):
print(kwargs)
pass
#调用
# keyFunc(1,2,3) 不可以传递的
dictA={'name':'peter','age':'35'}
keyFunc(**dictA)
#可理解为这个函数体就是对字典类型进行操作的
keyFunc(name='peter',age='25')
# 也可以直接在括号内传入字典
keyFunc()#也可以单独使用
def complexFunc(*args,**kwargs):
print(args)
print(kwargs)
pass
# complexFunc(1,2,3,4,name='林俊杰')
# complexFunc(age=36)
# def Test(**kwargs,*args):
# '''
# 可选参数必须放到关键字参数之前
# :param kwargs:
# :param args:
# :return:
# '''
# pass
#可选参数:接受的是一个元组类型
#关键字参数:接受的是一个字典类型
返回值:
# 函数返回值
# 具体类似C++中的函数定义,不在多做笔记
#同样时return 返回对应的数据类型
三个函数运用的案例
#写函数,接受N个数字,求这些参数数字的和
def sum1(*args):
result=0
for item in args:
result+=item
pass
return result
effect=sum1(1,2,3,4,5,6,7,8,9,10)
print(effect)
#写函数,找出传入的列表或元组的奇数位对应的元素,并返回一个新的列表
def fuc2(con):
site1=1#传入列表的位置坐标
result_list=[]
for item in con:
if site1%2!=0:
result_list.append(item)# 为什么result_list[site1]=item 会报错
site1+=1
return result_list
test1=[1,2,3,4,5,6]
test2=('w','a','n','g','p','e','n','g','c','a','n')
print(fuc2([1,2,3,4,5,6]))
print(fuc2(test2))
#检查传入字典的每一个value的长度,如果大于2,那么仅仅保留前两个长度的内容,并将新的内容返回给调用者。
#字典中的value只能是字符串或列表
def fuc3(dicexample):
result={}
for key,value in dicexample.items():#遍历全部的关键字和值
if len(value)>2:
result[key]=value[:2]#向字典添加数据
else:
result[key]=value
pass
pass
return result
pass
#函数调用
test3={'数字':[1,2,3,4,5,6,],}
print(fuc3(test3))
全局变量和局部变量
#局部变量 就是函数内部定义的变量【作用域仅仅局限在函数的内部】
#不同的函数 可以定义相同的局部变量,但是搁在用各自的,不会产生影响
#局部变量的作用:为了临时的保存数据,需要在函数中定义来进行存储
def printInfo():
name='peter'
print('{}'.format(name))
pass
def TestMethod():
name='刘德华'
print(name)
pass
#----------------------全局变量---------------------
pro='计算机科学与技术'
# 在所定义的函数中都能运用这个变量
# 两者的作用范围不同
#-----------------当我们外部定义的变量名称与函数内部的变量名称相同时---------------
name='1233'
print(printInfo())
#-------------------我们输出的还是函数内部变量的值
# 如果要在函数内部对全局变量进行修改的话 要使用 globa
def change1():
global name
name='我已经被修改'
pass
change1()
print(name)
匿名函数,lambda
# python中使用lambda关键字创建匿名函数,
# 所谓匿名函数,即这个函数没有名字,不用def关键字创建标准的函数
#lambda 参数1,参数2,参数3:执行代码语句
#使用lambda表达式计算两个数和
test=lambda x,y:x+y
test(1,3)
test(4,5)
#特点
# 1.使用lambda关键字去创建函数
# 2.没有名字的函数
# 3.匿名函数冒号后面的表达式有且只有一个,注意:是表达式,而不是语句
# 4.匿名函数自带return,而这个return的结果就是表达式计算后的结果
#缺点
#lambda 只是单个表达式,不是一个代码块,lambda的设计就是为了满足简单函数的场景
#仅仅能封装有限的逻辑,复杂逻辑实现不了,必须用def来处理
#lambda与三元运算
# if a:
# b
# else:
# c
# 能够由以下等效的表达式来模拟
# b if a else c
# 这样的表达式(三元运算)能够放在lambda中,它们能够在lambda函数中实现选择逻辑
greater=(lambda x,y:x if x>y else y)
greater(3,5)
greater(6,2)
print(greater(3,5))
print(greater(6,2))
#打印结果
#C:\Users\admin\AppData\Local\Programs\Python\Python39\python.exe D:/desktop/study/函数/匿名函数,lambda.py
#5
#6
#也可以是:
age=15
print('可以参军'if age>18 else '继续上学')#可以替换传统双分支的写法
#也有这种形式
rs=(lambda x,y: x if x>y else y)(16,12)#直接的调
print(rs)
varRS=lambda x:(x**2)+890
print(varRS(10))
递归函数
# 递归函数
#求阶乘
#用循环的话
def jiechneg(n):
result=1
for item in range(1,n+1):
result*=item
pass
return result
print('10的阶乘%d'%(jiechneg(10)))
#递归的方法
def digui_jiehceng(n):
'''
递归实现
:param n:
:return:
'''
if n==1:
return 1
else:
return n*digui_jiehceng(n-1)
pass
print(digui_jiehceng(10))
# 优点:逻辑简单,定义简单
# 缺点:容易导致栈溢出,内存资源紧张,甚至内存溢出
递归案例——文件操作模块的,树形结构遍历
#递归案例: 模拟实现 树形结构的遍历
import os #文件操作模块
def findFile(file_Path):
listRs=os.listdir(file_Path)#这个语句目的:获取该路径下所有文件夹
for fileItem in listRs:
full_path=os.path.join(file_Path,fileItem)#获取完整的文件路径
if os.path.isdir(full_path):#判断是否是文件夹
findFile(full_path)#如果是一个文件夹,再次去递归
pass
else:
print(fileItem)
pass
pass
else:
return
pass
#调用搜索文件对象
findFile('D:\\desktop')
python中的内置函数
数学运算内置函数
#取绝对值
print(abs(-34))
#round 取近似值
print(round(3.66,1))#逗号后面是你想要保留的小数点后几位
# pow 求次方
print(pow(3,3))#求三的三次方
#divmod 求商和余数
divmod(7,3)
divmod(9,3)
#max()求最大值
print(max(80,100,1000))
print(max([23,123,23,4,3,56,78,98,76,6,5665,4,5]))
#sum()求和
print(sum([0,1,2,-1]))
print(sum((2,3,4),1))
print(sum([0,1,2,3,4],2))
#迭代是一个可以遍历的对象
#迭代是一个可以遍历的对象
#迭代是一个可以遍历的对象
print(sum(range(50),3))
#eval 执行表达式
a,b,c=1,2,3
print(eval('a+b+c'))
print(eval('a*b+c'))
def fuc1():
print('1234')
pass
eval('fuc1()')
print(eval('a+b+c',{'c':3,'a':1,'b':3}))
#变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。
类型转换函数
#chr()数字转换字符
# 描述:char()用一个范围在range(256)内的(就是0~255)整数作参数,返回一个对应的字符
# 语法:chr(i)
# 参数:i可以是10进制也可以是16进制的形式的数字
# 返回值:返回值是当前整数对应的ascll字符
# print(chr(96))
# 二进制转换
# print(bin(10))#转换成二进制
# print(hex(32))#十六进制转换
#元组转换为列表
tup=()
# print(type(tup))
li=list(tup)
li.append('强制转换成功')
# print(li)
tuplist=tuple(li)
# print(type(tuplist))#列表转换为元组
dic=dict()
print(type(dic))
dic['name']='王钰'
dic['age']='14'
print(dic)
dic=dict(name='王鹏灿',age='20')
print(dic)
#转换为字节数组 bytes()
print(bytes('我喜欢python',encoding='utf-8'))
序列操作函数
#all()函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为TRUE,如果是
#返回True,否则返回False元素,除了是0、空、FALSE外都算是TRue
# 注意:空元组、空列表、返回值都为True,这里要特别注意
print(all([]))#True
print(all(()))#True
print(all([1,2,3,False]))
print(all((3,4,0)))
# 只要有一个是False,就是False
#any() 函数用为判断给定的可迭代参数 iterable 是否全部为Fals
#则返回False,则返回False,如果有一个True,则返回True
#元素除了0、空、FALSE 外都算是True
print(any({1,2,3,False}))
#只要有一个是True都为True
# sorted()与sort 区别:
# sort 是应用在list上的方法,sorted可以对所有迭代的对象进行排序操作
# list的sort方法返回的是对已经存在的列表进行操作,而内建函数sorted方法返回的是一个新的list,而不是在原来的基础上进行的操作
li=[2,45,1,67,23,10]
# li.sort()#list的排序方法
# print(li)#修改的直接是原始对象
#元组一但定义就不可能改变所以 元组没有sort函数
print('--------------排序之前----------------{}'.format(li))
# varList=sorted(li)默认升序
varList=sorted(li,reverse=True)
print('--------------排序之后----------------{}'.format(varList))
tup=(2,45,1,67,23,10)
tup1=sorted(tup,reverse=False)
print(tup1)
#range()函数可创建一个整数列表,一般用在for循环中
# 默认为1的步长,range(0,5)等价于range(0,5,1)
#从0开始,到4结束,步长为1
# zip()函数用于讲可迭代的对象作为参数,将对象中对应的元素
# 打包成一个个元组,然后返回由这些元组组成的列表
# zip():就是用来打包的
s1=['a','b','c']
s2=['你','我','他']
print(list(zip(s1)))#压缩一个数据
zipList=zip(s1,s2)#运行两个数据
print(list(zipList))
# 打印结果:[('a', '你'), ('b', '我'), ('c', '他')]
s3=['你','我','他','hah','enen ']
zipList2=zip(s1,s3)
print(list(zipList2))
# 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同
# 打印结果
# [('a', '你'), ('b', '我'), ('c', '他')]
zipList3=zip(s1,s2,s3)
print(list(zipList3))
# 打印结果:
# [('a', '你', '你'), ('b', '我', '我'), ('c', '他', '他')]
# 案例:
def prinBookInfo():
books=[]#存储所有的图书信息
bookId=input('请输入编号:每个项以空格分隔开')
bookName=input('请输入书名:每个项以空格隔开')
bookPos=input('请输入位置:每个项以空格隔开')
idList=bookId.split(' ')
nameList=bookName.split(' ')
posList=bookPos.split(' ')
bookInfo=zip(idList,nameList,posList)#打包处理
for bookItem in bookInfo:
'''
遍历图书信息进行存储
'''
dicInfo={'编号':bookItem[0],'书名':bookItem[1],'位置':bookItem[2]}
books.append(dicInfo)#将字典对象添加到list容器中
pass
for item in books:
print(item)
pass
# prinBookInfo()
#打印结果:
# 请输入编号:每个项以空格分隔开1 2 3
# 请输入书名:每个项以空格隔开python java C++
# 请输入位置:每个项以空格隔开a1 b1 c1
# {'编号': '1', '书名': 'python', '位置': 'a1'}
# {'编号': '2', '书名': 'java', '位置': 'b1'}
# {'编号': '3', '书名': 'C++', '位置': 'c1'}
# enumerate()函数用于将一个可遍历的数据对象
# (如列表、元组、字符串)组合为一个索引序列,同时
# 列出数据和数据下表,一般用在for循环当中
listObj=['a','b','c']
for item in enumerate(listObj):
print(item)
# 打印结果:
# (0, 'a')
# (1, 'b')
# (2, 'c')
# 打印结果是一个元组形式,我们也可以单独讲元素拿出来
listObj=['a','b','c']
for index,item in enumerate(listObj):
print(index,item)
# 打印结果:
# 0 a
# 1 b
# 2 c
#还可以自己默认是从哪些下标开始
listObj=['a','b','c']
for index,item in enumerate(listObj,5):
print(index,item)
#打印结果:
# 5 a
# 6 b
# 7 c
dicObj={'name':'李易峰','hobby':'唱歌','pro':'演员'}
for item in enumerate(dicObj):
print(item)
#打印结果:
# (0, 'name')
# (1, 'hobby')
# (2, 'pro')
#是字典的Key
for item in enumerate(dicObj):
print(item[1])#可以只打元组的第二个位置,也就是Key值,也可以:
for index,item in enumerate(dicObj):
print(item)#这种情况可以直接拿走key值数据
set函数
#set 不支持索引和切片,是一个无序的且不重复的容器
#类似于字典 但是只有key 没有value
#创建集合
set1={1,2,3,}
print(type(set1))
#添加操作
set1.add('python')
print(set1)
#清空操作
# set1.clear()
# print(set1)
set2={2,3,4}
#取差集 a.difference(b) a 中存在,b 中不存在 结果返回了一个新的set
x=set2.difference(set1)
print(set1.difference(set2))
print(x)
print(set2-set1)
print(set1)
#交集操作
# print(set1.intersection(set2))
# print(set2&set1)
#并集操作
print(set1.union(set2))
print(set1|set2)
#pop 操作 就是从集合中拿数据,并且同时删除,就是set中的这个数据去除
print(set1)
getData=set1.pop()
print(getData)
print(set1)
#pop拿出的是非负最小正整数 包括0
print(set1.discard(3))#指定移除的元素
print(set1)
# updata 更新集合 两个集合
set1.update(set2)
print(set1)
#在set1上的更新,原set集合中
三个例题作业
#求三组连续自然数的和:求出1到10,20到30,35到45 的三个和
a=sum(range(1,11))
b=sum(range(20,31))
c=sum(range(35,46))
print(eval('a+b+c'))
def sumRange(m,n):
'''
求和
:param m:
:param n:
:return:
'''
return sum(range(m,n+1))
print(sumRange(1,10))
print(sumRange(20,30))
print(sumRange(35,40))
#100个和尚吃100个馒头,大和尚一人吃三个馒头,小和尚三人吃一个馒头,请问大小和尚各多少人
for a in range(1,100):
if a*3+(100-a)/3==100:
print('大和尚{}人 小和尚{}人'.format(a,100-a))
#指定一个列表,列表里含有唯一一个只出现过一次的数字,写出程序找出这个"独一无二"的数字
list1=[1,2,4,5,4,3,4,7,6,5,7,6,7,8,9,0,8,7,5,7,9,0,]
set1=set(list1)
for item in set1:
list1.remove(item)
pass
set2=set(list1)#这是重复元素的集合
#用循环
# for i in set1:
# if i not in set2:
# print(i)
# pass
# pass
#用difference
print(set1.difference(set2))
面向对象编程(上)
面向对象与面向过程:
#面向对象编程:OOP[object oriented programming]是一种python的编程思想
#面向过程:就是我们一开始学习的,按照解决问题的步骤去写代码
#【根据业务逻辑去写代码】
# 从计算机角度来看:面向过程不适合做大项目
# 面向对象更适合做大项目
# 面向过程的关注点是:怎么做
# 面向对象的关注点是:谁来做
# 面向对象与面向对象编程
# 面向对象:按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型
# ,模拟客观世界分析、设计、实现软件的办法。
# 面向对象编程:是一种解决软件复用的设计和编程方法。这种方法把软件系统中相近似的操作逻辑
# 和操作应用数据、状态,以类的形式描述出来,以对象实例的形式在软件系统中复用,以达
# 到提高软件开发效率的作用。
类和对象
# 类和对象
# 类:类是具有一组 相同或者相似特征【属性】和行为的一系列对象的组合
# 现实世界 计算机世界
# 行为----------方法
# 特征----------属性
# 对象:对象是实实在在的一个东西,类的实例化
# 类是对象的抽象化 而对象是类的一个实例
# 类的抽象
# 具有相同(或者类似)属性和行为的一系对象的集合都可以抽象出一个类
# 例如: 小明开着他家的宝马去逛街
# 小明-> 可以抽象出人类
# 宝马->可以抽象出车类
#
# 再例如:
# 抽象坦克大战中的类
# 坦克
# 类名: Tank
# 属性:血量 类型
# 方法:移动,发射子弹
# 墙
# 类名:Wall
# 属相:血量 类型
# 方法:阻挡
# 子弹
# 类名:Bullet
# 属性:杀伤力
# 定义类和对象
#类结构 类名 属性 方法
# class 类名:
# 属性
# 方法
class Person:
'''
对应人的特征
'''
name='小明'
age=20
'''
对应人的行为
'''
def eat(self):
print('大口吃饭')
pass
def run(self):
print('飞快地跑')
pass
pass
#规则格式 对象名=类名()
xm=Person()#创建一个对象 类的实例化
xm.eat()#调用函数
xm.run()
print('{}的年龄是:{}'.format(xm.name,xm.age))
实例方法与属性
class Person:
'''
对应人的特征
'''
# name='小明' #类属性
# age=20 #类属性
'''
对应人的行为 实例方法
'''
def __init__(self):
self.name='小明' #实例属性
pass
def eat(self):#实例方法
print('大口吃饭')
pass
def run(self):
print('飞快地跑')
pass
pass
def printInfo():
'''
普通方法
:return:
'''
pass
#创建另外一个实例对象
xw=Person()
xw.run()#实例方法调用
# 实例方法:再类的内部,使用def 关键字来定义 第一个参数默认是self
# 【名字标识可以是其他的名字,但是这个位置必须被占用】
# 实例方法是归于 类的实例所有
# 属性:再类的内部定义的变量称为 【类属性】
# 实例属性:定义在方法里面使用self引用的属性称之为实例属性
# def __init__(self):
# self.name='小明' #实例属性
# pass
# 在方法内部定义的【通过类似于self.变量名】变量,是实例属性
# 在方法内部定义的变量【类属性】
魔术方法:
__ init __函数
#__init__
#1.python 自带的内置函数 具有特殊的函数 使用双下划线 包起来的【魔术方法】
#2.是一个初始化的方法 用来定义实例属性 和初始化数据的,在创建对象时自动调用,不用手动调用
#3.利用传参的机制可以让我们定义功能更加强大方便的类
# __init__使用
# class pepole:
# def __init__(self):
# self.name='小倩'
# self.sex='女生'
# self.age='20'
# pass
#
# def eat(self):#实例方法
# print('是刷说、')
# pass
# xq=pepole()
# print(xq.name,xq.sex,xq.age)
#改进
class pepole:
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
pass
def eat(self,food):#实例方法
print(self.name+'喜欢吃'+food)
pass
zp=pepole('张鹏','男生','18岁')
print(zp.name,zp.sex,zp.age)
zp.eat('香蕉')
# 打印结果:
# 张鹏 男生 18岁
# 张鹏喜欢吃香蕉
理解self
# self和对象指向同一个地址,可以认为就是对象的引用
# class Person:
# '''
# 定义类
# '''
# def eat(self):
# '''
# 实例方法
# :return:
# '''
# print('self=%d'%id(self))
# pass
# pass
#
# xw=Person()
# print('xw=%d'%id(xw))
# xw.eat()
# 运行结果:
# xw=2994867510048
# self=2994867510048
# 地址一项
# self 传参问题
# 所谓self ,可以理解为对象自己,某个对象调用其方法时,python解释器
# 会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参
# 数即可。
class Person:
def __init__(self,pro):
self.pro=pro#实例属性的定义
pass
'''
定义类
'''
def eat(mypro,name,food):
'''
实例方法
:return:
'''
print('%s喜欢吃%s 修的专业是:%s'%(name,food,mypro.pro))
pass
pass
xw=Person('计算机')#需要填写init中的实例属性的对象
print('xw=%d'%id(xw))
xw.eat('小王','香蕉')
#小结:
#self 只有在类中定义 实例方法的时候才有意义,在调用时候不必传入相应的参数
# 而是由解释器 自动去指向
# self 的名字是可以更改的 可以定义成其他名字,只是约定俗成的定义成了self
#self指的是 类实现对象本身,相当于Java中this
__ str __ 函数
#__str__方法:
#出现的问题:
#·直接打印对象,输出结果只是一串类似id地址的信息。
# class pepole:
# def __init__(self,name,sex,age):
# self.name=name
# self.sex=sex
# self.age=age
# pass
#
# def eat(self,food):#实例方法
# print(self.name+'喜欢吃'+food)
# pass
#
# xw=pepole('小王','男','20')
# print(xw)
# 打印结果:
# <__main__.pepole object at 0x00000243BC84EFD0>
# 出现的结果只是对象的地址
# 运用__str__之后:
class pepole:
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
pass
def eat(self,food):#实例方法
print(self.name+'喜欢吃'+food)
pass
def __str__(self):
return '名字是:%s 性别%s 年龄%s'%(self.name,self.sex,self.age)
xw=pepole('小王','男','20')
print(xw)
# 打印结果:
# 名字是:小王 性别男 年龄20
__ new __函数
# __new__方法:
class pepole:
def __init__(self,name,sex,age):
self.name=name
self.sex=sex
self.age=age
print('-----init----函数执行')
pass
def eat(self,food):#实例方法
print(self.name+'喜欢吃'+food)
pass
def __str__(self):
return '名字是:%s 性别%s 年龄%s'%(self.name,self.sex,self.age)
def __new__(cls, *args, **kwargs):
'''
创建对象实例的方法 每调用一次 就会生成一个新的对象 cls 就是class的缩写
场景:可以控制创建对象的一些属性限定 经常用来做单例模式的时候来使用
:param args:
:param kwargs:
'''
print('__new__函数的执行')
return object.__new__(cls)#在这里是真正创建对象实例的
pass
pass
xw=pepole('小王','男','20')
print(xw)
new 与 init 的区别
#n__new__和__init__函数的区别
#__new__类的实例化方法 必须返回该实例 否则对象创建不成功
#__init__用来做数据属性的初始化工作,也可以认为是实例的构造方法 接受类的实例 self并对其进行构造
#__new__至少有一个参数是clas 代表要实例化的类,此参数在实例化时由python解释器自动提供
#__new__函数执行要早于__init__函数
案例游戏:
#第一步 需要定义一个类【角色类】
import time#导入时间的包
class role:
def __init__(self,name,hp):
'''
构造初始化函数
:param name:
:param hp:
'''
self.name=name
self.hp=hp
pass
def tong(self,enemy):
'''
敌人的状态变化
:param enemy:
:return:
'''
#敌人减掉10滴血
enemy.hp-=10
info='【%s】 tong了【%s】一刀,hp-10'%(self.name,enemy.name)
print(info)
pass
def kanren(self,enemy):
'''
敌人的状态变化
:param enemy:
:return:
'''
#敌人减20滴血
enemy.hp-=15
info='【%s 】kan了【%s】一刀,hp-15'%(self.name,enemy.name)
print(info)
pass
def chiyao(self):
'''
吃药补血的方法
:return:
'''
self.hp+=10
info='【%s】吃了一颗补血药,增加了十滴血'%(self.name)
print(info)
pass
def __str__(self):
return '%s当前血量状态为%s:'%(self.name,self.hp)
#创建两个实例化对象【西门吹雪】【叶孤城】
xmcx=role('西门吹雪',100)
ygc=role('叶孤城',100)
while True:
if xmcx.hp<=0 or ygc.hp<=0:
# 满足条件 退出循环
break
xmcx.tong(ygc)#西门吹雪捅了叶孤城一刀
print(xmcx)#打印对象状态
print(ygc)
print('-------------------------------------------')
ygc.tong(xmcx)
print(xmcx)#打印对象状态
print(ygc)
print('-------------------------------------------')
xmcx.chiyao()
print(xmcx)#打印对象状态
print(ygc)
time.sleep(1)#休眠暂停一秒钟
print('----对战结束------')
面向对象编程(中)
继承
# 在python中展现面向对象的三大特征
# 封装、继承、多态
# 封装:指的是把内容封装到某个地方。便于后面的使用
# 他需要:
# 把内容封装到某个地方
# 从另一个地方去调用被封装的内容
# 对于封装来说 其实就是使用初始化构造方法将内容封装到对象中,然后通过对对象直接
# 或者self来获取被封装的内容
# 继承: 和现实中的继承是一样的: 也就是
# 子可以继承父的内容[属性和行为](爸爸有的儿子都有,相反,儿子有的爸爸不一定有)
class Animal:
def eat(self):
'''
吃
:return:
'''
print('吃饭了')
pass
def drink(self):
'''
喝
:return:
'''
print('喝水了')
pass
class Dog(Animal):#继承了Animal父类 此时dog就是子类
def wwj(self):
'''
子类独有的实现
:return:
'''
print('小狗叫')
pass
pass
class Cat(Animal):
def mmj(self):
print('小猫喵喵叫')
pass
pass
d1=Dog()
d1.eat()#具备了吃的行为,是继承了父类的行为
c1=Cat()
c1.eat()
# 所以对于面向对象的继承来说 其实就是讲多个类共有的方法提取到父类中
# 而子类仅需继承父类而不必一一实现
#这样就可以极大的提高效率 减少代码的重复编写,精简代码的层级结构 便于拓展
# class 类名(父类):
# pass
# 多继承:
# 子类可以继承一个父类,那是否可以继承两个父类或多个呢?
# 答案是肯定的,这就是python的多继承
# class 类名(父类1,父类2):
# pass
# 例如:
class shenxian:
def fly(self):
print('神仙都会飞')
pass
pass
class Monkey:
def chitao(self):
print('猴子喜欢吃桃')
pass
pass
class Sunyukong(shenxian,Monkey):
pass
swk=Sunyukong()
swk.chitao()
swk.fly()
# 继承的过程中会出现方法重名的问题,我们该怎么去查找呢?该怎么执行呢?
class D(object):
def eat(self):
print('D.eat')
pass
pass
class C(D):
def eat(self):
print('C.eat')
pass
pass
class B(D):
def eat(self):
print('B.eat')
pass
class A(C,B):#父类中如果都有共同的名称的函数时候,先执行放在第一位的父类中的函数
# def eat(self):
# print('A.eat')
pass
a=A()
a.eat()
#在执行eat的方法时 查找方法的顺序是
# 首先到A中里面查找 如果A中没有 ,则继续的去B类中去查找,B类中没有,则去C类中查找,有的话执行eat函数,无的话继续找到D类
# 广度优先遍历
# A-B-C-D 也是继承顺序
# 类的间接继承,即父类没有此方法,直接调用爷爷的类
# 类的传递过程中,我们把父类称为基类,子类又称为派生类,父类的属性和方法可以一级一级的传递到子类
重写和调用父类方法
# 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖父类中同名的方法
# 为什么要重写,父类的方法已经不满足需要,那么子类就可以重写父类或者完善父类的方法
class Dog:
def __init__(self,name,color):
self.name=name
self.color=color
def bark(self):
print('汪汪叫....')
pass
pass
# class kejiquan(Dog):
# # def __init__(self):#属于重写父类的方法
# # pass
# def bark(self):
# print('叫的跟狗一样...')#直接重写
# print(self.name)#子类已不具备父类的实例属性
# pass
# 如果子类中无init函数的重写,那么直接调用父类的属性函数
# 那么我们重新构造一下
class kejiquan(Dog):
def __init__(self,name,color):#属于重写父类的方法
#针对这种需求 我们就需要去调用父类的函数了
# Dog.__init__(self,name,color)#手动调用调用父类的方法了,执行完毕就可以具备name,color这两个实例属性
super().__init__(name,color)#super 是自动找到父亲 进而调用方法,假设继承了多个父类,逐个查找知道找到并且调用即可
#拓展其他属性
self.height=20
self.weight=20
pass
def bark(self):
super().bark()#调用父类的方法
print('叫的跟狗一样...')#直接重写
print(self.name)
pass
kj=kejiquan('柯基犬','红色')
kj.bark()
析构方法
# 析构方法的概述
# 当一个对象被删除或者被销毁时,python解释器也会默认调用一个方法,这个方法为__del__(),也称为析构方法
class Animal:
def __init__(self,name):
self.name=name
print('这是构造初始化方法')
pass
def __del__(self):
print('当在某个作用域下面 没有被使用[引用]的情况下 解析器会自动的调用此函数 来释放内存空间')
print('这是析构方法')
print('%s 这个对象 被彻底清理了 内存空间也释放了'%self.name)
pass
pass
cat=Animal('小花猫')
# 运行结果:
# 这是构造初始化方法
# 这是析构方法
# 当我们再加上一句代码
input('程序等待中......')
print('*'*40)
# 运行结果:
# 这是构造初始化方法
# 程序等待中......
# 所以说del 是在所有程序执行完之后再默认执行的
dog=Animal('柯基小狗')
#加上后面的dog代码之后
# 运行结果:
#
# 这是构造初始化方法
# 程序等待中......ll
# ****************************************
# 这是构造初始化方法
# 当在某个作用域下面 没有被使用[引用]的情况下 解析器会自动的调用此函数 来释放内存空间
# 这是析构方法
# 小花猫 这个对象 被彻底清理了 内存空间也释放了
# 当在某个作用域下面 没有被使用[引用]的情况下 解析器会自动的调用此函数 来释放内存空间
# 这是析构方法
# 柯基小狗 这个对象 被彻底清理了 内存空间也释放了
# 后面的小狗代码也被直接释放内存了
# 用del cat 代码也可以直接手动删除对象
# 析构函数总结:
# 1.当整个程序脚本执行完毕后会自动调用del 方法
# 2.当对象被手动销毁时也会自动调用del方法
# 3.析构函数一般用于资源回收,利用del方法销毁对象回收内存资源
类属性和实例属性
# 类属性的修改必须有类本身去修改,而定义的实例对象不但能对其进行修改
# 类定义的对象修改类属性后,仅仅作用与对象本身,对全局的类属性无任何影响
类方法和静态方法
class People:
country='China'
#类方法 用classmetho 来进行修饰
@classmethod
def get_country(cls):
return cls.country#访问类属性,且只能访问类方法
pass
@classmethod
def change_country(cls,data):
cls.country=data#修改类属性的值,在类方法中
pass
# print(People.get_country())#通过类对象去引用
# p=People()
# print('实例对象访问%s'%p.get_country())
# p.change_country('英国')
# print(People.get_country())#通过类对象去修改国家,并且引用
# 静态方法:
# 类对象所拥有的方法,需要@staticmethod来表示静态方法,静态方法不需要任何参数
class People:
country='China'
#类方法 用classmetho 来进行修饰
@classmethod
def get_country(cls):
return cls.country#访问类属性,且只能访问类方法
pass
@classmethod
def change_country(cls,data):
cls.country=data#修改类属性的值,在类方法中
@staticmethod
def getData():
return People.country
print(People.getData())
p=People()
print(p.getData())#注意 一般情况下,我们不会通过实例对象去访问静态方法
#为什么要使用静态方法?
#由于静态方法主要是存放逻辑性的代码,本身和类以及实例对象没有交互
#也就是说,在静态方法中,不会涉及到类方法和属性操作
#数据资源能够得到有效充分利用
#例如
import time #引入第三方的时间模块
class TimeTest:
def __init__(self,hour,min,second):
self.hour=hour
self.min=min
self.second=second
pass
@staticmethod
def showTime():
return time.strftime('%H:%M:%S',time.localtime())
pass
print(TimeTest.showTime())
t=TimeTest(2,10,15)
print(t.showTime())
#可以见的,通过实例对象调用静态函数是没必要的,是不能影响到静态函数的
# 总结:
# 从方法的形式可以看出来
# 1类方法的第一个参数是 cls 进而去引用类对象的属性和方法,必须使用装饰器@classmethond
# 2实例方法的第一个参数必定是self 通过这个self可以去引用类属性或者实例属性,若存在相同名称
# 实例属性和类属性,实例属性优先级最高
# 3静态方法不需要定义额外的参数,若是要引用属性的话
# 则可以通过类对象或者实例对象去引用即可 必须使用装饰器@staticmethond来装饰
多态
# 多态概念:
# 所谓多态:定义时的类型和运行时的类型不一样,此时就称为多态
# 顾名思义就是多种状态、形态,就是同一种行为
# 对于不同的子类【对象】有着不同的行为表现
# 要想实现多态 必须有两个前提需要遵守:
# 1、继承:多态必须发生在父类和子类之间
# 2、重写:子类重写父类的方法
#案例演示:
class animal:
'''
父类【基类】
'''
def say_who(self):
print('我是一个动物')
pass
pass
class Duck(animal):
'''
继承父类animal的子类 派生类【子类】
'''
def say_who(self):
'''
重写父类的方法
:return:
'''
print('我是一只漂亮的鸭子')
pass
pass
class Dog(animal):
'''
小狗类【子类】派生
'''
def say_who(self):
print('我是一只哈巴狗')
class cat(animal):
def say_who(self):
print('我是一只小猫咪')
class stduent(animal):
def say_who(self):
print('我是初三学生 王钰')
# duck1=Duck()
# duck1.say_who()
# dog1=Dog()
# dog1.say_who()
# cat1=cat()
# cat1.say_who()
# 运行结果:
# 我是一只漂亮的鸭子
# 我是一只哈巴狗
# 我是一只小猫咪
# 这就是同一种行为不同的表现,多态
def commonInvoke(obj):
'''
统一调用的方法
:param boj:
:return:
'''
obj.say_who()
listobj=[Duck(),Dog(),cat(),stduent()]
for item in listobj:
'''
循环去调用函数
'''
commonInvoke(item)
# 多态有什么用:
# 多态可以增加程序的灵活性
# 增加程序的拓展性
#鸭子类型duck typing
#在程序设计中,鸭子类型 时动态类型的一种风格,在这种风格中,一个对象有效的语义,
# 不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。“鸭子测试”可以这样表述:
# “当看到一只鸟走走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
# 在鸭子类型中,关注的不是对象的类型本身,而是它如何使用的。