Python基础
chap6 列表
- 列表的创建与删除
- 列表的查询操作
- 列表元素的增、删、改操作
- 列表元素的排序
- 列表推导式
列表
为什么要使用列表
- 变量可以存储一个元素,而列表是一个“大容器”可以存储N多个元素,程序可以方便的对这些数据进行整体操作
- 列表相当于其他语言中的数组
列表的创建
- 列表需要使用[],元素之间使用英文逗号分隔
- 列表的创建方式有以下两种
- 使用[]->list=["张三","李四",23]
- 使用内置函数list()->list=list(["张三","李四",23])
列表的特点
- 列表元素按顺序有序排序
- 索引映射唯一数据
- 列表可以存储重复数据
- 任意数据类型混淆
- 根据需要动态分配和回收内存
获取列表中指定元素的索引
- index()
- 如果查询列表中存在n个相同的元素,返回第一个元素的索引
- 如果查询的元素在列表中不存在,报错
- 还可以在指定的索引范围内进行查找
- 索引有正向索引和逆向索引,正向索引从0开始,逆向索引从-1开始
列表元素的查询操作
- 获取列表中的多个元素
- 语法格式:列表名[start:stop:step]
- 语法格式:列表名[start:stop:step]
list=[10,20,30,40,50,60,70,80]
print(id(list))
# step默认为1
# 切片的结果是一个新列表
list2=list[1:5]
print(id(list2))
# step为正数,切片的第一个元素默认是列表的第一个元素
print(list[:3:1])
# step为正数,切片的最后一个元素默认是列表的最后一个元素
print(list[3::1])
# step为负数,切片的第一个元素默认是列表的最后一个元素
print(list[:3:-1])
# step为负数,切片的最后一个元素默认是列表的第一个元素
print(list[3::-1])
- 列表元素的判断及遍历
- 用in和not in 判断元素在列表中是否存在
- 列表元素遍历使用for in
list=[10,20,30,40,50,60,70,80]
print(10 in list)
print(90 not in list)
for item in list:
print(item)
- 列表元素的增加操作
list=[10,'hello',30,'world',50]
print(id(list))
print(list)
# 在列表末尾添加一个元素
list.append('人生苦短')
print(id(list))
print(list)
# 在列表末尾至少添加一个元素
list2=[1,2,3]
list.extend(list2)
print(list)
# 在列表的任意位置添加一个元素
list.insert(1,'zhaosi')
print(list)
# 在列表的任意位置添加至少一个元素
list[2::]=list2;
print(list)
- 列表元素的删除操作
list=[10,20,30,40,50,60,20,70,80]
print(list)
# 一次删除一个元素,重复删除第一个,不存在则报错
list.remove(20)
print(list)
# list.remove(8)
# 删除指定索引处的元素,不指定索引,删除最后一个,指定索引不存在则报错
list.pop(1)
print(list)
list.pop()
print(list)
# 切片删除操作
list[5::]=[]
print(list)
# 清空列表
list.clear()
print(list)
# 删除列表
del list
print(list)
- 列表元素的修改操作
- 为指定索引的元素赋予一个新值
- 为指定的切片赋予一个新值
list=[10,20,30,40,50,60,20,70,80]
# 为指定索引的元素赋予一个新值
list[3]=30
print(list)
# 为指定的切片赋予一个新值
list[4:6]=[100,100,100]
print(list)
- 列表元素的排序操作
- 常见的两种方式
- 调用sort()方法,列表中的所有元素按照从小到大的顺序排序,可以指定reverse=True进行降序排序,原列表发生改变
- 调用内置函数sorted(),可以指定reverse=True进行降序排序,原列表不发生改变,产生一个新的列表对象
- 常见的两种方式
# 调用sort()方法,列表中的所有元素按照从小到大的顺序排序,可以指定reverse=True进行降序排序
print('-----------------------------------------------')
list=[52,32,12,42,1,100,56,43]
print(list,id(list))
list.sort()
print(list,id(list))
list=[52,32,12,42,1,100,56,43]
print(list)
list.sort(reverse=True)
print(list)
# 调用内置函数sorted(),可以指定reverse=True进行降序排序,原列表不发生改变
print('-----------------------------------------------')
list=[52,32,12,42,1,100,56,43]
print(list,id(list))
newList=sorted(list)
print(list,id(newList))
list=[52,32,12,42,1,100,56,43]
print(list)
newList=sorted(list,reverse=True)
print(newList)
- 列表生成式
# 要求列表的元素为2, 4, 6, 8, 10
list=[i*2 for i in range(1,6)]
print(list)
chap7 字典
- 什么是字典
- 字典的原理
- 字典的创建和删除
- 字典的查询操作
- 字典元素的增、删、改操作
- 字典推导式
什么是字典
-
python内置的数据结构之一,与列表一样是一个可变序列
-
以键值对的方式存储数据,字典是一个
无序
序列,键是不可变序列 -
整数和字符串都是不可变序列,字典和列表是可变序列
-
字典示意图
字典的实现原理
- 字典的实现原理与查字典类似,查字典是根据部首或拼音来查找对应的页码,python中的字典是根据key来查找value对应的位置,查找效率高,因为无论有多少个键值对,都需要计算键的hash值来查找
字典的创建
- 最常用的方式:使用花括号
- 使用内置函数dict()
# 使用花括号
dic={'name':'张三','age':56,'gender':"男",'info':'张三烤肉'}
print(dic)
# 使用内置函数dict()
dic2=dict(name='张三',age=56,gender="男",info='张三烤肉')
print(dic2)
字典的常用操作
字典元素的获取
- 字典中获取元素的两种方式:
- []取值
- get()取值
- []取值和get()取值的区别
- []中如果是字典中不存在key,则抛出keyerror异常
- get()取值方法,括号中如果是字典不存在的key,则返回none,可以通过参数设置value,以便指定的key不存在时返回
# score[]取值
dic={'name':'张三','age':56,'gender':"男",'info':'张三烤肉'}
print(dic['name'])
# print(dic['phone'])
# get()取值
print(dic.get('gender'))
# 可以通过参数设置value,以便指定的key不存在时返回
print(dic.get('phone',-1))
key的判断
字典元素的删除
- 格式:del dic['键']
字典元素的新增
- 格式:dic[key]=value
# 字典key的判断
dic={'name':'张三','age':56,'gender':"男",'info':'张三烤肉'}
print('name' in dic)
print('name' not in dic)
# 字典元素的增加
dic['phone']='13225365215'
print(dic)
# 字典元素的修改
dic['name']='大脚'
print(dic)
# 字典元素的删除
del dic['phone']
print(dic)
# 清空字典
dic.clear()
print(dic)
获取字典示图的三个方法
dic={'name':'张三','age':56,'gender':"男",'info':'张三烤肉'}
# 获取所有的key并转成列表
print(list(dic.keys()))
# 获取所有的value
print(dic.values())
# 获取所有的key value并转成元组
print(list(dic.items()))
字典元素的遍历
# 使用花括号
dic={'name':'张三','age':56,'gender':"男",'info':'张三烤肉'}
for item in dic:
print(item,dic[item],dic.get(item))
字典的特点
- 字典中的所有元素都是一个key-value对,key不允许重复,value可以重复
- 字典中的元素是无序的
- 字典中的key必须是不可变对象
- 字典也可以根据需要动态的伸缩
- 字典会浪费较大的内存,是一种使用空间换时间的结构
字典生成式
- 使用内置函数zip()
- 用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回这些元组组成的列表
items=['name','sge','gender']
prices=['大脚',52,1]
dic={item:price for item,price in zip(items,prices)}
print(dic)
chap 8 元组,集合
- 什么是元组
- 元组的创建方式
- 元组的遍历
- 什么是集合
- 集合的创建
- 集合的增删改查操作
- 集合生成式
什么是元组
- 元组
- python内置的数据结构之一,十一个不改变序列
- 不可变序列与可变序列
- 不可变序列:字符串、元组
- 不可变序列没有增删改操作
- 可变序列:列表、字典
- 可变序列:有增删改操作,对象地址不发生改变
- 不可变序列:字符串、元组
元组的创建方式
# 使用()
d1=('张三','李四','麻子')
print(d1)
# 使用括号创建,括号可以省略
d2='张三','李四','麻子'
print(d2)
# 使用括号创建,只有一个元素,逗号不能省略
d3=(52,)
print(d3,type(d3))
# 使用内置函数tuple()
d4=tuple(('张三','李四','麻子'))
print(d4,id(d4),type(d4))
# 创建空元组
d5=()
print(d5)
为什么要将元组设计成不可变序列?
- 再多任务环境下,同时操作对象时不需要加锁因此在程序设计中尽量使用不可变序列
注意事项
:元组中存储的对象是引用-
如果元组中对象本身不可变对象,则不能再引用其他对象
-
如果元组中对象本身可变对象,则可变对象的引用不允许改变,但数据可以变
-
元组的遍历
- 元组是可迭代对象,所以可以使用for-in进行遍历
d1=('张三','李四','麻子')
for item in d1:
print(item)
什么是集合
- python语言提供的内置数据结构
- 与列表字典一样都属于可变类型的序列
- 集合是没有value的字典
集合的创建方式
- 直接使用{}
- 使用内置函数set()
# 使用{}
s1={1,5,9,6,32,15,52}
print(s1,type(s1)) #集合是无序的
# 使用内置函数set()
s2=set(range(1,9))
print(s2)
# 可以将列表转为集合
print(set([5,2,63,7,56,42]))
# 可以将元组转为集合,集合是不重复的
print(set((1,1,2,663,5,5,5,9)))
# 将字符串转为集合
print(set('python'))
#
print(set({5,2,63,7,56,42}))
# 创建空集合
print(set())
集合的相关操作
集合元素的判断操作
- in或者not in
集合元素的新增操作
- 调用add()方法,一次添加一个元素
- 调用update()方法至少添加一个元素
集合元素的删除操作
- 调用remove()方法,一次删除一个指定元素,如果指定的元素不存在则抛出keyerror
- 调用discard()方法,一次删除一个指定元素,如果指定元素不存在不抛出异常
- 调用pop()方法,一次删除一个任意元素
- 调用clear()方法,清空集合
# 集合元素的判断操作
s1={1,5,9,6,32,15,52}
print(1 in s1)
print(9 not in s1)
# 集合元素的新增操作
s1.add(63)
print(s1)
s1.update((20,856,635))
print(s1)
s1.update([666,444,222,333])
print(s1)
# 集合元素的删除操作
# 调用remove()方法,一次删除一���指定元素,如果指定的元素不存在则抛出keyerror
s1.remove(444)
print(s1)
# s1.remove(999) KeyError: 999
# 调用discard()方法,一次删除一个指定元素,如果指定元素不存在不抛出异常
s1.discard(333)
print(s1)
s1.discard(999)
print(s1)
# 调用pop()方法,一次删除一个任意元素
s1.pop();
s1.pop();
print(s1)
# 调用clear()方法,清空集合
s1.clear()
print(s1)
集合间的关系
- 两个集合是否相等
- 可以使用运算符==或!=进行判断
- 一个集合是否是另一个集合的子集
- 可以调用方法issubset进行判断
- 一个集合是否是另一个集合的超集
- 可以调用方法issupperset进行判断
- 两个集合是否没有交集
- 可以调用方法isdisjoint进行判断
s1={10,20,30,40,50}
s2={20,10,40,30,50}
s3={10,20,30}
s4={60,70}
print(s1==s2)
print(s3.issubset(s1))
print(s2.issuperset(s3))
print(s2.isdisjoint(s3))
print(s4.isdisjoint(s3))
集合的数学操作
- 交集:使用函数intersection()或者&
- 并集:使用函数union()或者|
- 差集:使用函数difference()或者-
- 对称差集:使用函数symmetric_difference()或者^
s1={10,20,30,40}
s2={20,30,40,50}
# 交集:使用函数intersection()或者&
print(s1.intersection(s2))
print(s1&s2)
# 并集:使用函数union()或者|
print(s1.union(s2))
print(s1|s2)
# 差集:使用函数difference()或者-
print(s1.difference(s2))
print(s1-s2)
# 对称差集:使用函数symmetric_difference()或者^
print(s1.symmetric_difference(s2))
print(s1^s2)
集合生成式
s1={i*i for i in range(10)}
print(s1)
列表、字典、元组、集合的对比
chap9 字符串
- 字符串的驻留机制
- 字符串的常用操作
- 字符串的比较
- 字符串的切片操作
- 格式化字符串
- 字符串的编码转换
字符串的驻留机制
- 字符串:在python中字符串是基本数据类型,是一个不可变的字符序列
- 字符串驻留机制:仅保存一份想同且不可变字符串的方法,不同的值呗存放在字符串的驻留池中,python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,二是把字符串的地址赋给新创建的变量
- 驻留机制的几种中情况(交互模式)
- 字符串的长度为0或1时
- 符合标识符(字母数字下划线)的字符串
- 字符串仅在编译时进行驻留,而非运行时
- [-5,256]之间的整数数字
- sys中的intern方法强制两个字符串指向同一个对象
- pycharm对字符串进行了优化处理
- 字符串驻留机制的优缺点
- 当需呀值相同的字符串时,可以直接从字符串池中拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的
- 在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join方法是先计算出所有字符串的长度,然后再拷贝,只new一次对象,比+的效率高。
>>> a=''
>>> b=''
>>> print(a is b)
True
>>> c='%'
>>> c='%'
>>> d='%'
>>> print(c is d)
True
>>> e='123%'
>>> f='123%'
>>> print(e is f)
False
>>> a='123x_'
>>> b='123x_'
>>> print(a is b)
True
>>> a='abc'
>>> b='a'+'bc'
>>> c='a'.join('bc')
>>> print(a is b)
True
>>> print(a is c)
False
>>> a='-5'
>>> b='-5'
>>> print(a is b)
False
>>> a=-5
>>> b=-5
>>> print(a is b)
True
字符串的常用操作
字符串的查询操作
s1='hello,hello'
print(s1.index('lo'))
print(s1.rindex('lo'))
print(s1.find('lo'))
print(s1.rfind('lo'))
# print(s1.index('k')) ValueError
# print(s1.rindex('k')) ValueError
print(s1.find('k'))
print(s1.rfind('ko'))
字符串的大小写转换操作
a='hello'
b=a.upper() # 转换成一个新的字符串
print(a,id(a))
print(b,id(b))
c='WORLd'
d=c.lower() # 转换成一个新的字符串
print(c,id(c))
print(d,id(d))
e='HeLLo'
f=e.swapcase() # 转换成一个新的字符串
print(e,id(e))
print(f,id(f))
i='heLLo'
j=i.capitalize() # 转换成一个新的字符串
print(i,id(i))
print(j,id(j))
m='hello world good night'
n=m.title() # 转换成一个新的字符串
print(m,id(m))
print(n,id(n))
字符串内容的对齐操作
s='hello,python'
# 居中对齐
print(s.center(20,"#"))
# 给的长度小于字符串长度,返回原字符串
print(s.center(10))
# 左对齐
print(s.ljust(20,"*"))
# 给的长度小于字符串长度,返回原字符串
print(s.ljust(10))
# 第二个参数不给,默认为空格
print(s.ljust(20))
# 右对齐
# 第二个参数不给,默认为空格
# 给的长度小于字符串长度,返回原字符串
print(s.rjust(20,"1"))
# 右对齐,默认用0补齐
print(s.zfill(20))
字符串的劈分操作
s="hello world python"
s1="你好|世界|人生苦短|我用Python"
# 从左劈分
lis1=s.split()
print(lis1)
# param1:根据什么来分隔 param2:最大分隔次数
lis2=s1.split("|",maxsplit=1)
print(lis2)
# 从右边劈分
lis3=s.rsplit()
print(lis3)
lis4=s1.rsplit("|",maxsplit=2)
print(lis4)
字符串的判断
# 判断指定的字符串是不是合法的标识符 isidentifier()
print("abc_123".isidentifier())
print("赵四".isidentifier())
print("赵四%".isidentifier())
print("-------------------------------------")
# 判断指定的字符串是否全部由空白字符(回车,换行,水平表符)组成 isspace()
print("\t".isspace())
print("\tabc".isspace())
print(" ".isspace())
print("-------------------------------------")
# 判断指定的字符串是否全部由字母组成 isalpha()
print("abc".isalpha())
print("张三".isalpha())
print("abc123".isalpha())
print("-------------------------------------")
# 判断指定的字符串是否全部由十进制数字组成 isdecimal()
print("123".isdecimal())
print("#123".isdecimal())
print("0123".isdecimal())
print("0123四".isdecimal())
print("-------------------------------------")
# 判断指定的字符串是否全部由数字组成 isnumeric() 罗马数字为true
print("123".isnumeric())
print("123四".isnumeric())
print("123张三".isnumeric())
print("-------------------------------------")
# 判断指定的字符串是否全部由字母和数字组成 isalnum()
print("123".isalnum())
print("123abn".isalnum())
print("123谢大脚".isalnum())
print("123——————".isalnum())
字符串的替换与合并操作
# 字符串的替换
s1="hello,python"
print(s1.replace("python","java"))
s2="hello python python python"
# param1:old str param2:new str param3:最大替换次数
print(s2.replace("python","java",2))
#字符串的合并
s3=["hello","java","python"]
print("|".join(s3))
s4="hello"
print("*".join(s4))
字符串的比较操作
- 运算符:>,>=,<,<=,==,!=
- 比较规则:首先先比较两个字符串中的第一个字符,如果相等则继续比较下一个字符,依次比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中所有后续字符将不再被比较
- 比较原理:两个字符串进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符的原始值,与内置函数ord对应的是内置函数chr,调用内置函数chr时可以得到其对应的字符
注意:'is'比较的id,'=='比价的是value
print("abc"=="abc")
print("abc">"ab")
print("apple">"banana")
print(ord("a"))
print(ord("b"))
print(chr(97))
print(chr(98))
字符串的切片操作
- 字符串是不可变类型,不具备增删改操作,切片操作将产生新字符串
s1='hello,python'
print(s1[:5:])
print(s1[0:5:])
print(s1[0:8:2])
print(s1[::-1])
print(s1[:-6:-1])
格式化字符串
name="张三"
age=18
# %格式化
print("大家好,我叫%s,今年%d岁了" % (name,age))
# format格式化
print("大家好,我叫{0},今年{1}岁了".format(name,age))
# f-string格式化(3.0以上版本才能用)
print(f"大家好,我叫{name},今年{age}岁了")
print("%10d" % 99) # 10表示的是总宽度
print("%.3f" % 3.14526655) # .3f表示的是保留的小数位数
print("%10.3f" % 3.14526655) # 10表示的是总宽度;.3表示的是保留的小数位数
print("{}".format(3.25566)) # 花括号里的索引可以省略,但建议写上
print("{0:.3}".format(3.25566)) # .3表示一共是3位数,0表示索引,可省略
print("{0:10.3}".format(3.25566)) # 同时设置宽度和精度; .3表示一共是3位数,0表示索引,可省略
print("{0:.3f}".format(3.25566)) # .3f表示的是保留的小数位数,0表示索引,可省略
print("{:.3f}".format(3.25566)) # .3f表示的是保留的小数位数,0表示索引,可省略
print("{0:10.3f}".format(3.25566)) # 同时设置宽度和精度;.3f表示的是保留的小数位数,0表示索引,可省略
字符串的编码与转码
- 编码与解码的的方式
- 编码:将字符串转换为二进制数据(bytes)
- 解码:将bytes类型的数据转换成字符串类型
s="把酒问明月"
# 编码
print(s.encode("GBK")) # 在GBK这种编码格式中 一个字符占2个字节
print(s.encode("UTF-8")) # 在UTF-8这种编码格式中 一个字符占3个字节
# 解码
# 只能用对应的编码格式来解码,否则会报错
byte=s.encode("GBK")
print(byte.decode("GBK"))
byte=s.encode("UTF-8")
print(byte.decode("UTF-8"))
chap10 函数
- 函数的创建和调用
- 函数的参数传递
- 函数的返回值
- 函数的参数定义
- 变量的作用域
- 递归函数
函数的创建和调用
什么是函数
- 函数就是执行特定任务和以完成特定功能的一段代码
为什么需要函数
- 复用代码
- 隐藏实现细节
- 提供可维护性
- 提高可读性便于调试
函数的创建
def add(a,b):
c=a+b
return c
sum=add(10,30)
print(sum)
函数的参数传递
- 函数调用的参数传递
- 位置实参
- 根据形参对应的位置进行实参传递
- 关键字实参
- 根据形参名称进行实参传递
- 位置实参
def add(a,b): # a,b称为形式参数,简称形参,形参的位置在函数的定义处
c=a+b
return c
sum=add(10,30) # 10,20称为实际参数,简称实参,实参的位置在函数的调用处
print(sum)
sum=add(b=10,a=30) # =左侧的变量名称称为:关键字参数
print(sum)
- 函数调用的参数传递内存分析图
- 在函数调用的过程中,进行形参的传递
- 如果实不课表对象,在函数体的修改不会影响实参的值
- 如果实可变对象,在函数体内的修改会影响实参的值
- 在函数调用的过程中,进行形参的传递
def change(arg1,arg2):
print('arg1',arg1)
print('arg2',arg2)
arg1=100
arg2.append(10)
print('arg1', arg1)
print('arg2', arg2)
return
# - 如果实不课表对象,在函数体的修改不会影响实参的值
# - 如果实可变对象,在函数体内的修改会影响实参的值
n1=11
n2=[12,53,46]
change(n1,n2)
print('n1',n1)
print('n2',n2)
函数的返回值
- 若干函数没有返回值,return可以省略不写
- 函数的返回值如果是一个,直接写返回类型
- 函数的返回值如果是多个,返回结果为元组
def fun(num):
odd=[] #存奇数
even=[] #存偶数
for i in num:
if i%2:
odd.append(i)
else:
even.append(i)
return odd,even
lst=[30,56,12,43,97,3]
print(fun(lst))
# 若干函数没有返回值,return可以省略不写
def fun1():
print("hello")
fun1()
# 函数的返回值如果是一个,直接写返回类型
def fun2():
return 'python'
print(fun2())
# 函数的返回值如果是多个,返回结果为元组
def fun3():
return 'hello','python','world'
print(fun3())
函数的参数定义
默认值参数
- 函数设置时,给参数设置默认值,只有与默认值不符合的时候,才需要传递实参
def fun1(a,b=10):
print(a,b)
fun1(20)
fun1(20,30)
个数可变的位置参数
- 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数
- 使用*定义可变的位置形参
- 结果为一个元组
def fun1(*arg):
print(arg)
fun1(10,20,30)
个数可变的关键字形参
- 定义函数时,可能无法事先确定传递的关键字实参的个数时,使用可变的关键字形参
- 使用* * 定义可变的位置形参
- 结果为一个字典
def fun2(**arg):
print(arg)
fun2(a=10,b=20,c=30)
个数可变的位置参数和个数可变的关键字形参在一个函数中不能同时定义多个
函数参数总结
def fun1(a,b,c,d):
print("a",a)
print("b",b)
print("c",c)
print("d",d)
return
fun1(10,20,30,40)
lst=[11,22,33,44]
fun1(*lst) # 函数调用时,将列表中的每个元素都转换为位置实参传入
fun1(a=1,b=2,c=3,d=4)
dic={'a':111,'b':222,'c':333,'d':444}
fun1(**dic) # 函数调用时,将字典中的每个元素都转换为位置实参传入
print("--------------------------------------")
fun1(20,30,c=50,d=60) # 前两个采用的位置实参传递,而c,d采用的是关键字实参传递
"""需求:c,d只能采用关键字实参传递"""
def fun2(a,b,*,c,d):
print("a", a)
print("b", b)
print("c", c)
print("d", d)
return
def fun2(a,b,*,c,d,**arg):
print("a", a)
print("b", b)
print("c", c)
print("d", d)
print("arg", arg)
return
def fun3(*args,**arg):
print("args", args)
print("arg", arg)
return
变量的作用域
- 变量作用域
- 程序代码能访问该变量的区域
- 根据变量的有效范围可分为
- 局部变量 -在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会成为全局变量
- 全局变量
- 函数体外定义的变量,可作用与函数内外
def fun1(a):
b=10
print(a)
print(b)
# print(a) 报错 a是局部变量
# print(b) 报错 b是局部变量
# name是全局变量,函数内外都可使用
name="zahosi"
def fun2():
print(name)
fun2()
print(name)
# -在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会成为全局变量
def fun1():
global c
c=20
print(c)
print(c)
递归函数
什么是递归函数
- 如果一个函数在该函数体内调用了函数本身,这个函数就称为递归函数
递归函数的组成部分
- 递归调用与递归中止条件
递归的调用过程
- 每递归调用一次函数,都会在栈内分配一个栈帧
- 每执行完一次函数,都会释放相应的空间
递归的优缺点
- 优点:思路和代码简单
- 缺点:占用内存多,效率低下
def fac(n):
if n==1:
return 1
else:
return n*fac(n-1)
print(fac(6))
斐波那契数列
- 斐波那契数列指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
def fib(n):
if n==1:
return 1
elif n==2:
return 1
else:
return fib(n-1)+fib(n-2)
print(fib(6))
chap11 BUG
- Bug的由来及分类
- 不同异常类型的处理方式
- 异常处理机制
- pyCharm的调试模式
Bug的由来及分类
- bug的由来:此处省略
- bug的类型:
input输入的都是字符串,常涉及转型
异常处理机制
- 多个except的结构
- 捕获异常的顺序的顺序是按照先子类后父类的顺序,为了避免遗漏可能出现的异常,可以在最后增加BaseException
try:
a = int(input('请输入第一个数'))
b = int(input('请输入第一个数'))
print(a/b)
except ZeroDivisionError:
print('除数不能为零')
except BaseException:
print('出现异常')
- try...except..else结构
- 如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块
try:
a = int(input('请输入第一个数'))
b = int(input('请输入第一个数'))
result= a/b
except ZeroDivisionError:
print('除数不能为零')
except BaseException:
print('出现异常')
else:
print(result)
- try-except-else-finally结构
- finally块无论是否发生异常都会被执行,常用来释放try块中申请的资源
try:
a = int(input('请输入第一个数'))
b = int(input('请输入第一个数'))
result= a/b
except ZeroDivisionError:
print('除数不能为零')
except BaseException:
print('出现异常')
else:
print(result)
finally:
print("任务执行完毕")
- 常见异常
traceback模块的使用
- 使用traceback模块来打印异常信息
import traceback
try:
print("---------------------------")
print(2/0)
except :
traceback.print_exc()
pyhcharm开发环境的调试
- 断点:程序运行到此处,暂时挂起,停止起步,此时可以详细的观察程序运行的情况,反方便做出经一步的判断
chap12 编程思想
- 两大编程思想
- 类和对象的创建
- 类对象与类属性
- 类方法与静态方法
编程思想
类与对象
- 类
- 类是多个类似事物组成的群体的总称。能够帮助我们快速理解和判断事物的性质
- 数据类型
- 不同的数据类型属于不同的类
- 使用内置函数可以查看数据类型
- 对象
- 100,333,520都是int类下包含的相似的不同个例,这个个例专业术语称为实例或对象
类的创建
- 创建类的语法:
-
class Student: pass
-
- 类的组成:
- 类属性
- 实例方法
- 静态方法
- 类方法
class Student:
local='云南' # 类的属性
#实例方法
def addMethod(self,name,age):
self.name=name
self.age=age # self.name和self.age称为实体属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
print("我是一个实例方法")
#静态方法
@staticmethod
def deleteMethod():
print("使用@staticmethod注解,所以我是静态方法")
#类方法
@classmethod
def updateMethod(cls):
print("使用@classmethod注解,所以我是类方法")
#函数
def selectMethod():
print("定义在类之外,我是个函数")
对象的创建
-
对象的创建有称为类的实例化
-
语法: 实例名=类名()
-
意义:有了实例,就可以调用类中的方法
class Student:
local='云南' # 类的属性
def __init__(self,name,age):
self.name=name
self.age=age # self.name和self.age称为实体属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
#实例方法
def addMethod(self):
print("我是一个实例方法")
#静态方法
@staticmethod
def deleteMethod():
print("使用@staticmethod注解,所以我是静态方法")
#类方法
@classmethod
def updateMethod(cls):
print("使用@classmethod注解,所以我是类方法")
#对象的创建
studentA=Student("大脚",23)
#方法调用——方法1
studentA.addMethod()
studentA.deleteMethod()
#方法调用——方法2 静态方法和类方法才能用类名直接点
Student.addMethod(studentA)
类属性,类方法,静态方法的使用
- 类属性:类中方法外的变量称为类属性,被该类的所有对象共享
- 类方法:使用@classmethod修饰的方法,可以使用类名直接去访问
- 类方法:使用@staticmethod修饰的方法,可以使用类名直接去访问
class Student:
local='云南' # 类的属性
def __init__(self,name,age):
self.name=name
self.age=age # self.name和self.age称为实体属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
#实例方法
def addMethod(self):
print("我是一个实例方法")
#静态方法
@staticmethod
def deleteMethod():
print("使用@staticmethod注解,所以我是静态方法")
#类方法
@classmethod
def updateMethod(cls):
print("使用@classmethod注解,所以我是类方法")
#类属性的获取
print(Student.local)
studentA=Student("大脚",23)
studentB=Student("广坤",23)
print(studentA.local)
print(studentB.local)
Student.local='上海'
print(studentA.local)
print(studentB.local)
#静态方法调用
Student.deleteMethod()
#类方法调用
Student.updateMethod()
动态绑定属性和方法
- Python是动态语言,在创建对象之后,可以动态的绑定属性和方法
class Student:
local='云南' # 类的属性
def __init__(self,name,age):
self.name=name
self.age=age # self.name和self.age称为实体属性,进行了一个赋值操作,将局部变量的name的值赋给实体属性
#实例方法
def eat(self):
print(self.name,"已经吃了")
studentA=Student("张三",23)
studentB=Student("李四",23)
studentA.eat()
studentB.eat()
# 绑定动态属性
studentA.gender=1
print(studentA.gender)
# 绑定动态方法
def drink():
print("喝了吗?")
studentA.drink=drink
studentA.drink()
chap13 面向对象
- 封装
- 继承
- 方法重写
- object类
- 多态
- 特殊方法和特殊属性
面向对象的三大特征
- 封装:提高程序的安全性
- 将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样无需关心内部的实现细节,从而隔离了复杂度
- 在PYTHON中没有专门修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前面使用两个'_'
class Car:
def __init__(self,carName):
self.carName=carName
def start(self):
print("汽车启动....",self.carName)
CarA=Car("奔驰")
CarA.start()
# 属性私有
class Student:
local='云南' # 类的属性
def __init__(self,name,age):
self.name=name
self.__age=age
def introduce(self):
print(self.name,self.__age)
studentA=Student("张三",20)
studentA.introduce()
print(studentA.name)
# print(studentA.__age) AttributeError: 'Student' object has no attribute '__age'
print(studentA._Student__age) #在类的外部用_Student__age进行访问
- 继承:提高代码的复用性
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def introduce(self):
print('我是',self.name,'今年',self.age,'岁了')
# 单继承
class Student(Person):
def __init__(self,name,age,gender):
super().__init__(name,age)
self.gender=gender
stu=Student("大脚",55,1)
stu.introduce()
# 多继承
class A(object):
pass
class B(object):
pass
class C(A,B):
pass
- 方法重写
- 如果子类对继承自弗雷的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写
- 子类重写后的方法可以通过super().xxx()调用父类中被重写的方法
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def introduce(self):
print('我是',self.name,'今年',self.age,'岁了')
# 单继承,方法重写
class Student(Person):
def __init__(self,name,age,gender):
super().__init__(name,age)
self.gender=gender
def introduce(self):
super().introduce()
print('性别',self.gender)
stu=Student("大脚",55,1)
stu.introduce()
- object类
- object类是所有类的父类,因此所有类都有object类的属性和方法
- 内置函数dir()可以查看指定对象的所有属性
- Object有一个__str__()方法,用于返回一个对于“对象的描”,对于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对__str__()进行重写
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '我叫{0},今年{1}岁了'.format(self.name,self.age)
stu=Person("大脚",55)
print(dir(stu))
print(stu)
- 多态:提高程序的可扩展性和可维护性
- 简单的说,多态就是具有多种形态,它指的是:几遍不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行的过程中根据变量所引用的对象的类型,动态的决定调用哪个对象中的方法
- 静态语言和动态语言
- 静态语言和动态语言关于多态的区别
- 继承
- 方法重写
- 父类引用指向子类对象
- 动态语言的多态崇尚“鸭子类型”,当看到一只鸟走起来像鸭子,游泳起来像鸭子,收起来也想鸭子,那么这只鸟就可以被称为鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为
- 静态语言和动态语言关于多态的区别
class Animal(object):
def eat(self):
print('动物会吃')
class Cat(Animal):
def eat(self):
print('猫吃猫粮')
class Dog(Animal):
def eat(self):
print('狗吃骨头')
class Person(object):
def eat(self):
print('人吃五谷杂粮')
def fun(obj):
obj.eat()
fun(Cat())
fun(Dog())
fun(Person())
fun(Animal())
特殊方法和特殊属性
特殊属性
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name):
self.name=name
# 创建C类的对象
x=C("赵四")
print(x.__dict__) # 实例对象的属性字典
print(C.__dict__) # 类对象的属性字典
print(x.__class__) # 对象所属的类
print(C.__bases__) # C类的父类类型元素
print(C.__base__) # C类的基类(最近的一个类)
print(C.__mro__) # 类的层次结构
print(A.__subclasses__()) # 子类列表
特殊方法
__add__
和__len__
class Student:
def __init__(self,name):
self.name=name
def __add__(self, other):
return self.name+other.name
def __len__(self):
return len(self.name)
studentA=Student("张三")
studentB=Student("李四")
result=studentA+studentB
print(result)
print(len(studentA))
__init__
和__new__
class Student(object):
def __init__(self,name,age):
print('init方法被调用了,self的id值为{0}'.format(id(self)))
self.name=name
self.age=age
def __new__(cls, *args, **kwargs):
print('new方法被调用了,cls的id值为{0}'.format(id(cls)))
obj=super().__new__(cls)
print('创建的对象的id值为{0}'.format(id(obj)))
return obj
print('object这个类对象的id值为{0}'.format(id(object)))
print('Student这个类对象的id值为{0}'.format(id(Student)))
studentA=Student("大脚",52)
print('studenA这个Student类对象的实例对象的id值为{0}'.format(id(studentA)))
# 运行结果如下:
# object这个类对象的id值为140705969040208
# Student这个类对象的id值为1919483311136
# new方法被调用了,cls的id值为1919483311136
# 创建的对象的id值为1919513616448
# init方法被调用了,self的id值为1919513616448
# studenA这个Student类对象的实例对象的id值为1919513616448
-
说明图
类的浅拷贝与深拷贝
- 变量的赋值操作 -只是形成两个变量,实际上还是指向同一个对象
- 浅拷贝 -Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用一个子对象
- 深拷贝 -使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu=cpu
self.disk=disk
# 变量的赋值 形成两个变量,实际上还是指向同一个对象
cpuA=CPU()
cpuB=cpuA
print(id(cpuA))
print(id(cpuB))
print(cpuA)
print(cpuB)
# 类的浅拷贝
print('---------------类的浅拷贝---------------')
diskA=Disk()
computerA=Computer(cpuA,diskA)
import copy
computerB=copy.copy(computerA)
print(computerA,computerA.cpu,computerA.disk)
print(computerB,computerB.cpu,computerB.disk)
# 深拷贝
print('---------------深拷贝---------------')
computerC=copy.deepcopy(computerA)
print(computerA,computerA.cpu,computerA.disk)
print(computerC,computerC.cpu,computerC.disk)
说明图
chap 模块
- 什么叫模块
- 自定义模块
- 以主程序的形式执行
- python中的包
- 第三方模块的安装及使用
什么叫模块
- 模块英文为modules
- 函数与模块的关系
- 一个模块中可以包含N多个函数
- 在python中一个扩展名为.py的文件就是一个模块
- 使用模块的好处
- 方便其它程序和脚本的导入使用
- 避免函数名和变量名冲突
- 提高代码的可维护性
- 提高代码的可重用性
自定义模块
- 创建模块
- 新建一个.py文件,名称尽量不要与python自带的标准模块相同
- 导入模块
import 模块名称 [as别名]
from 模块名称 import 函数/变量/类
# 导入模块中所有方法
import math
print(id(math))
print(type(math))
print(dir(math))
print(math.ceil(3.6))
print(math.floor(2.3))
print(math.tan(1/2))
print(math.pow(2,3))
from math import pi
print(pi)
from math import pow
print(pow(2,3))
以主程序的形式执行
转载自:https://juejin.cn/post/6913089009250107405