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
#在程序设计中,鸭子类型 时动态类型的一种风格,在这种风格中,一个对象有效的语义,
# 不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。“鸭子测试”可以这样表述:
# “当看到一只鸟走走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
# 在鸭子类型中,关注的不是对象的类型本身,而是它如何使用的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值