导图社区 python_基础语法
在这个思维导图中,您将学习Python的基本数据类型、运算符、条件语句、循环语句、函数、模块、文件操作等知识。这些基础语法将为您打下坚实的编程基础,有助于您更好地理解和应用Python的高级功能。 除了学习Python基础语法外,购买这个思维导图还有以下优势: 省时省力:这个思维导图可以帮助您更快地掌握Python基础语法,避免花费大量时间和精力在学习基础知识上。 高效学习:这个思维导图采用了图形化的方式呈现知识点,让您更容易理解和记忆。 灵活性:这个思维导图可以轻松地打印或在电子设备上查看,让您随时随地都可以学习Python基础语法。 实用性:这个思维导图还包括了一些实用的代码示例,让您更深入地理解Python基础语法的应用。
编辑于2023-08-01 17:36:14 山西经典好书,精准的可以翻译为电影语言的技法,场面调度 剪辑的经典之作,这本书干货很多,我对每个部分进行了总结,对部分内容进行了补充,对语法进行了重点标注,看不懂的朋友辅助例子看,还是很容易理解的。有些朋友说混乱的例子让很多人都读不下去,各种越轴,各种抽象,但是视听语法没问题,其实看不懂就是对重点语法没理解,例子不是重点,只是作者为了帮助我们理解视听语言的中心语法,希望对于喜欢这本干货的朋友有所帮助!
很多人都会觉得年终总结很难,因为要整理很多数据,还要写很多报告。有时候,他们甚至不知道应该从哪里开始。 不过,好消息来了!我们有一套神奇的“年终总结模板”,可以帮助你们轻松完成这个任务。
机会在哪里?用户痛点在哪?7个来源帮你看清本质.人人都知道创新的重要性,但关键问题是,该如何进行创新呢?随本脑图看看吧!
社区模板帮助中心,点此进入>>
经典好书,精准的可以翻译为电影语言的技法,场面调度 剪辑的经典之作,这本书干货很多,我对每个部分进行了总结,对部分内容进行了补充,对语法进行了重点标注,看不懂的朋友辅助例子看,还是很容易理解的。有些朋友说混乱的例子让很多人都读不下去,各种越轴,各种抽象,但是视听语法没问题,其实看不懂就是对重点语法没理解,例子不是重点,只是作者为了帮助我们理解视听语言的中心语法,希望对于喜欢这本干货的朋友有所帮助!
很多人都会觉得年终总结很难,因为要整理很多数据,还要写很多报告。有时候,他们甚至不知道应该从哪里开始。 不过,好消息来了!我们有一套神奇的“年终总结模板”,可以帮助你们轻松完成这个任务。
机会在哪里?用户痛点在哪?7个来源帮你看清本质.人人都知道创新的重要性,但关键问题是,该如何进行创新呢?随本脑图看看吧!
python
基础知识
语言介绍
优势
600多种语言,python擅长爬虫,数据分析,AI等
开发效率第一
模块库很多,方便开发者使用
学习曲线第一
学习难度低
生态圈第一
89年诞生后,发展出了强大的生态圈
缺点
运行速度较慢
应用领域
WEB开发
网络编程
爬虫
云计算
人工智能,数据分析
自动化运维
金融分析
科学运算
游戏开发
写代码
执行python代码的两种方式
python交互器
供调试测试使用
写在文件里
永久保存,随时执行
开发软件都要写在文件里
第一次代码
print("hello world")
print("hello world")
print("hello worldsssss.")
运行cmd,然后执行
变量
内存就像一个仓库
变量可以被看作是一个容器,用于存储值。就像一个盒子一样,变量名是这个容器的标签,用于标识这个容器中存储的值的类型和用途。变量值是实际存储在容器中的数据或对象。 内存地址可以被看作是容器在计算机内存中的位置。就像一个盒子在仓库中的位置一样,内存地址指示着这个容器在内存中的确切位置,从而允许程序找到并访问这个容器中的值。
变量名
容器的标签
name
age
变量值
货物
Alex Li
23
内存地址
盒子在仓库中的位置
id(name)
id(age)
先定义,后调用
变量的定义规则
在程序全局都会用到的变量,尽量定义在文件开头。
变量名只能是字母,数字或下划线的任意组合,其他形式均不合法
变量名的第一个字符不能是数字
以下关键字不要声明为变量名['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except','exec, 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try','while', 'with', 'yield], 这些是Python语法中已经占用了的关键字
常用变量的命名规范
驼峰体
每个单词首字母大写
下划线(推荐)
禁止
用拼音、中文做变量名
变量名过长
不能让人通过名字就能看出来是什么意思
首字母大写(大写是用来定义类名的,后面会学)
变量的修改和删除
修改
变量名+变量值
name = “金角大王”
name = "Alex"
name2 = name
name2= "alex"
修改name = "Jack"
结果name2 = "Alex"
变量名不会指向变量名,只会指向变量值
删除
del+变量名
del name
基本数据类型
python的数据类型
数字类型
整数
你存的所有的整数,都是这个类型
int(整型)integer
1.数字不加引号 ,加了引号叫字符串。 2.type()方法来查看数据类型
浮点
float(浮点型)
即小数
字符串
str
在python中,加了引号的字符都被认为是字符串
单引号
双引号
没有任何区别,只有考虑单双的配合,避免混淆逻辑错误
多引号
多行字符串,必须用多引号,开始用单结尾就用单,开始用双结尾就用双。
\n
换行符
字符串拼接
数字可进行加减乘除的运算,字符串也可以,但是只能进行相加和相乘运算
字符串只能与字符串运算,不能和数字或其他类型拼接
数据类型-⼜见str
字符串定义
字符串是一个有序的字符的集合,用于在计算机里存储和表示文本信息
创建
s = "Hello, my name is Alex,golden king."
下标(字符串特性)
按照从左到右的顺序定义字符集合,下标从0开始顺序访问,有序. "下标”又叫“索引”,就是编号。比如火车座位号,座位号的作用:按照编号快速找到对应的座位。同理,下标的作用即是通过下标快速找到对应的数据。
可进行切片操作
序列[开始位置下标:结束位置下标:步长] 注意 1.不包含结束位置下标对应的数据,正负整数均可; 2.步长是选取间隔,正负整数均可,默认步长为1。
下标和步长为负数是倒叙字符串,-1表示倒数一个数字
如果下标的方向和步长方向冲突,则不可以print答案
>>> s 'Hello, my name is Alex,golden king.' >>> s[3:6] # 'lo,' >>> s[1:5] 'ello' >>> s[0:5] 'Hello' >>> >>> s[3:10] 'lo, my ' >>>
不可变,字符串是不可变的,不能像列表一样修改其中某个元素,所有对字符串的修改操作其实都是相当于生成了一份新数据。
字符串输出
print('hello world') name = 'Tom' print('我的名字是%s'%name) print(f'我的名字是{name}')
字符串输入
name=input('请输入您的名字:') print(f'您输入的名字是{name}') print(type(name)) password=input('请输入您的密码:') print(f'您输入的密码是{password') print(type(password))
字符串常用操作
下图标红框的为重点必须掌握的用法
三类
查找
所谓字符串查找方法即是查找子串在字符串中的位置或出现的次数。 find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。 1.语法 字符串序列.find(子串,开始位置下标,结束位置下标) 注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
mystr = "hello world and itcast and itheima and Python" print(mystr.find('and'))#12 print(mystr.find('and',15,30))#23 print(mystr.find('ands'))#-1
·idex0:检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。 1.语法 字符串序列.index(子串,开始位置下标,结束位置下标) 注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
mystr "hello world and itcast and itheima and Python" print(mystr.index('and')) # 12 print(mystr.index('and',15,30)) # 23 print(mystr.index('ands')) # 报错
·rfind0:和find()功能相同,但查找方向为右侧开始。 ·rindex(0:和index(0功能相同,但查找方向为右侧开始。
count():返回某个子串在字符串中出现的次数 语法 字符串序列.count(子串,开始位置下标,结束位置下标) 注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
mystr ="hello world and itcast and itheima and Python" print(mystr.count('and')) # 3 print(mystr.count('ands')) # 0 print(mystr.count('and',0,20)) # 1
修改
所谓修改字符串,指的就是通过函数的形式修改字符串中的数据。 ·replace():替换 1.语法 字符串序列.replace(旧子串,新子串,替换次数) 注意:替换次数如果查出子串出现次数,则替换次数为该子串出现次数。
字符串是不可变数据类型,只能通过赋值新的变量修改
mystr = "hello world and itcast and itheima and Python" new_mystr = mystr.replace("and", "he", 1) print(new_mystr)
split():按照指定字符分割字符串。 语法 字符串序列.split(分割字符,num) 注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。
mystr = "hello world and itcast and itheima and Python" list1 = mystr.split("and", 2) print(list1)
·joi():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。 语法 字符或子串.join(多字符串组成的序列)
new_mylist = ["aa", "bb", "cc"] new_str = "...".join(new_mylist) print(new_str)
capitalize0:将字符串第一个字符转换成大写。 mystr "hello world and itcast and itheima and Python" #结果:Hello world and itcast and itheima and python print(mystr.capitalize()) 注意:capitalize(0函数转换后,只字符串第一个字符大写,其他的字符全都小写。
title(0:将字符串每个单词首字母转换成大写。 mystr ="hello world and itcast and itheima and Python" #结果:Hello World And Itcast And Itheima And Python print(mystr.title())
●lower():将字符串中大写转小写。 mystr= "hello world and itcast and itheima and Python" #结果:hello world and itcast and itheima and python print(mystr.lower())
upper():将字符串中小写转大写。 mystr "hello world and itcast and itheima and Python" #结果:HELLO WORLD AND ITCAST AND ITHEIMA AND PYTHON print(mystr.upper())
·Istrip0:删除字符串左侧空白字符。 >>mystr= " hello world and itcast and itheima and Python " >>mystr.lstrip() 'hello world and itcast and itheima and Python "
rstrip(0:删除字符串右侧空白字符。 >>> mystr=" hello world and itcast and itheima and Python " >>mystr.rstrip() " hello world and itcast and itheima and Python'
·strip():删除字符串两侧空白字符。 >>>mystr="hello world and itcast and itheima and Python" >>mystr.strip() 'hello world and itcast and itheima and Python'
·ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度的新字符串。 语法 字符串序列.ljust(长度,填充字符)
rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度的新字符串, 语法和ljust()相同。
center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度的新字符串, 语法和just()相同。
判断
所谓判断即是判断真假,返回的结果是布尔型数据类型:True或False.。
●startswith():检查字符串是否是以指定子串开头,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。 语法 字符串序列.startswith(子串,开始位置下标,结束位置下标)
●endswith():检查字符串是否是以指定子串结尾,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。 语法 字符串序列.endswith(子串,开始位置下标,结束位置下标)
isalpha(:如果字符串至少有一个字符并且所有字符都是字母则返回True,否则返回False。 mystr1 'hello' mystr2 'hell012345' #结果:True print(mystr1.isalpha()) #结果:False print(mystr2.isalpha())
isdigit():如果字符串只包含数字则返回True否则返回False。 mystr1 ='aaa12345' mystr2='12345' #结果:False print(mystr1.isdigit()) #结果:False print(mystr2.isdigit())
isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返回Tue,否则返回False。 mystr1 'aaa12345' mystr2='12345-' #结果:True print(mystr1.isalnum()) #结果:False print(mystr2.isalnum())
isspace():如果字符串中只包含空白,则返回True,否则返回False。 mystr1='12345' mystr2=" " #结果:False print(mystr1.isspace()) #结果:True print(mystr2.isspace())
布尔
布尔类型很简单,就两个值,一个True(真),一个False(假),主要用作逻辑判断
我现在有2个值, a=3, b=5,我说a>b你说成立么?我们当然知道不成立,但问题是计算机怎么去描述这成不成立呢?或者说a<b是成立,计算机又怎么描述这个公式是成立的呢?没错,布尔类型
计算机为什么要描述这种条件呢?因为接下来就可以根据条件结果来干不同的事情啦呀!比如
上面是伪代码,但是不是意味着, 计算机就可以根据判断结果不同,来执行不同的动作啦?
列表
如果要把全班的人名在内存里存下来,用上面的字符串类型可以做到,但取的时候不方便。
你print(names)它打印的是所有人的信息,如果想取出Rain,没办法(可以用字符串切割方式,但是很麻烦)。此时,用列表就比较合适。
因为列表的是通过下标来标记元素位置的,下标也可称为索引。下标从0开始,每添加一个元素,就自动+1
元素添加
元素的添加有2种方式,插入、追加
插入
插入指可以可以把一个新元素插入到列表的任意位置
追加
添加到列表的尾部
元素修改
直接根据下标找到元素重新赋值即可
元素删除
有2种删除方法,一个是下标删除,一个是元素值删除。
del法
remove法
>>names ['金角大王Alex','Jack','Rain','小明','Rachel',Mack','小强'] >>>names.remove("小明")#通过指定元素名删除,会删除从左开始找到的第一个小明, 如果有多个小明,则只删除找到的第一个。 >>names ['金角大王Alex','Jack','Rain','Rachel','Mack','小强'] >>del names [3 ] 通过指定下标删除
判断某元素是否在列表里
>>names ['金角大王Alex','Jack','Rain','Rachel','Mack','小强'] >>> >>> "Mack"in names True
数据类型-⼜见list
2.1 定义:
[]内以逗号分隔,按照索引,存放各种数据类型,每个位置代表一个元素
再回顾下列表的特点:
1.可存放多个值
2.按照从左到右的顺序定义列表元素,下标从0开始顺序访问,有序
name_list ['Tom','Lily','Rose'] print(name_list[0]) Tom print(name_list[1])#Lily print(name_list[2]) #Rose
3.可修改指定索引位置对应的值,可变
2.2 列表的增加操作
追加,数据会追加到尾部
>>> names['alex', 'jack'] >>> names.append("rain") >>> names.append("eva") >>> >>> names['alex', 'jack', 'rain', 'eva']
可以追加整个序列
如果append()追加的数据是一个序列,则追加整个序列到列表
插⼊,可插⼊任何位置
>>> names.insert(2,"") >>> names['alex', 'jack', '', 'rain', 'eva']
合并,可以把另一外列表的值合并进来
>>> n2 = ["","",""] >>> names=['alex', 'jack', '', 'rain', 'eva'] >>> names.extend(n2) >>> names['alex', 'jack', '', 'rain', 'eva', '', '', '']
列表嵌套
>>> names.insert(2,[1,2,3]) >>> names ['alex', 'jack', [1, 2, 3], '', 'rain', 'eva', '狗蛋', '绿毛', '鸡头'] >>> names[2][1]2
2.3 删除操作
del 直接删
>>> names ['alex', 'jack', [1, 2, 3], '', 'rain', 'eva', '', '', ''] >>> del names[2] >>> names ['alex', 'jack', '', 'rain', 'eva', '', '', '']
pop 删除
>>> names ['alex', 'jack', '', 'rain', 'eva', '', '', ''] >>> names.pop() # '' >>> names ['alex', 'jack', '', 'rain', 'eva', '', ''] >>> help(names.pop) >>> names.pop(1) # 'jack'
remove 删除
>>> names ['alex', 'jack', '', 'rain', 'eva', '', '', '', 'eva'] >>> names.remove("eva") # eva >>> names ['alex', 'jack', '', 'rain', '', '', '', 'eva']
clear 清空
>>> n2 ['', '', ''] >>> n2.clear() >>> n2 []
2.4 修改操作
>>> names ['alex', '', 'rain', 'eva', '', ''] >>> names[0] = "" >>> names[-1] = "" >>> names ['', '', 'rain', 'eva', '', '']
逆置:reverse() num_1ist=[1,5,2,3,6,8] num_list.reverse() #结果:[8,6,3,2,5,1] print(num_list)
排序:sort() 语法 列表序列.sort(key=None,reverse=False) 主意:reverse表示排序规则, reverse=True降序, reverse=False升序(默认)
2.5 查操作
>>> names ['', '', 'rain', 'eva', '', '', 'eva'] >>> >>> names.index("eva") #eva 3 >>> names.count("eva") #eva 2
·Ien():访问列表长度,即列表中数据的个数。 name_list ['Tom','Lily','Rose'] print(len(name_list))#
在不知道一个元素在列表哪个位置 的情况 下,如何 修改:
1.先判断 在不在列表里, item in list
2. 取索引, item_index = names.index("eva")
3.去修改, names[item_index] =“铁蛋”
列表复制
函数: copy() 防止原始数据被修改
name_list ['Tom','Lily','Rose'] name_li2 name_list.copy() #结果:[Tom',Li1y',‘Rose] print(name 1i2)
列表嵌套
所谓列表嵌套指的就是一个列表里面包含了其他的子列表。 应用场景:要存储班级一、二、三三个班级学生姓名,且每个班级的学生姓名在一个列表。 name_list=['小明',小红',小绿'],[Tom',Lily',‘Rose'],[张三',李四') 王五] 思考:如何查找到数据李四"? #第一步:按下标查找到李四所在的列表 print(name_list[2]) #第二步:从李四所在的列表里面, 再按下标找到数据李四 print(name_list[2][1])
2.6 切片
切片就像切面包,可以同时取出元素的多个值
names[start : end]
>>> names ['', '', 'rain', 'eva', '', '', 'eva'] >>> names[1:4] #4 ['', 'rain', 'eva']
注意:切片的特性是顾头不顾尾,即start的元素会被包含,end-1是实际取出来的值
简写
>>> n[0:4] ['alex', 'jack', ['makc', 'xxx'], ''] >>> n[:4] ['alex', 'jack', ['makc', 'xxx'], '']
取倒数后2个值
>>> n[0:4] ['alex', 'jack', ['makc', 'xxx'], ''] >>> n[:4] ['alex', 'jack', ['makc', 'xxx'], ''] >>> n[4:5] ['rain'] >>> n[4:6] # ['rain', 'eva'] >>> n[4:] # ['rain', 'eva'] # 倒着
倒着切
>>> names[-5:-1] ['rain', 'eva', '', '']
但其实我想要的是后5个,只打印了4个,'eva'这个值没出来,为什么,因为上面提到的顾头不顾尾可是想把后5个全取出来如何做呢?
>>> names[-5:] ['rain', 'eva', '', '', 'eva']
如果取前几个值,一样可以把:号左边的省掉
>>> names['', '', 'rain', 'eva', '', '', 'eva'] >>> names[0:3] ['', '', 'rain'] >>> names[:3] # ['', '', 'rain']
步长(跳着切)
names[start:end:step] #step 1
>>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a[0:7:2] #2 [0, 2, 4, 6]
简写
>>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> >>> a[::3] #31:start:end [0, 3, 6, 9]
2.7 排序&反转
排序
>>> a = [83,4,2,4,6,19,33,21] >>> a.sort() >>> a [2, 4, 4, 6, 19, 21, 33, 83]
反转
>>> names ['#', '4', '@', 'eva', 'rain', '', '', '', ''] >>> names.reverse() >>> names ['', '', '', '', 'rain', 'eva', '@', '4', '#']
2.8 循环列表
>>> for i in names: ... print(i) ... rain eva @ 4 #
打印索引
>>> for i in enumerate(n): ... print(i[0],i[1]) ... 0 Alex 1 alex 2 eva 3 rain 4 shit 5 黑姑娘
2.9 练习:班级分组⼩程序
你们班有55人,每个人的姓名&考试成绩存在一个大列表里,格式如下
需求:
现要求按考试成绩高低将学员们分成5组,全存在一个新的大列表里, 5组分别是90-100,80-89,70-79,60-69, 0-59
最终的数据格式如下:
new_stu_list = [ [ ["Alex",100], ["Rain",91], ], [ ["",79], ["Jack",78], ], .... .... ]
附:班级成绩列表
stu1ist=['李渊',82],['李世民',7],['侯君集',5],【'李靖',58],【'魏征', 41],【"房玄龄',64],['杜如晦',65],['柴绍',94],【'程知节',45],【'尉迟恭',94] ["秦琼',54],【'长孙无忌',85],【李存恭',98],['封德彝',16],['段志玄',44],【'刘 弘基',18],[徐世绩',86],[李治',19],[武则天',39],[太平公主',57],[韦后', 76],[李隆基',95],['杨玉环',33],['王勃',49],['陈子昂',91],['卢照邻',70], [杨炯',81],['王之涣',82],[安禄山',18],【'史思明',9],【张巡',15],[雷万 春',72],【李白',61],【高力士',58],[杜甫',27],[白居易',5],【王维',14], ['孟浩然',32],['杜牧',95],[李商隐',34],['郭子仪',53],['张易之',39],[张昌 宗',61],['来俊臣',8],[杨国忠',84],[李林甫',95],['高适',100],[王昌龄', 40],['孙思邈',46],['玄奘',84],[鉴真",90],[高骈',85],['狄仁杰',62],['黄 巢',79],【'王仙芝',16],["文成公主',13],[松赞干布',47],【薛涛',79],【'鱼玄 机',16],【'贺知章',20],['李泌',17],【韩愈',100],['柳宗元',88],['上官婉儿五 代十国:朱温',55],[刘仁恭',6],[丁会',26],[李克用',39],[李存勖',11], [葛从周',25],['王建',13],【刘知远',95],【石敬瑭',63],['郭威',28],['柴 荣',50],['孟昶',17],【'荆浩',84],【刘彟',18],【张及之',45],【杜宇',73], [高季兴',39],[喻皓',50],[历真',70],[李茂贞',6],["朱友珪',7],['朱友贞', 11],【刘守光,2]]
元组
一.元组的应用场景
思考:如果想要存储多个数据,但是这些数据是不能修改的数据,怎么做?
答:列表?列表可以一次性存储多个数据,但是列表中的数据允许更改。
一个元组可以存储多个数据,元组内的数据是不能修改的。
二.定义元组
元组特点:定义元组使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型。
#多个数据元组 t1=(10,20,30) #单个数据元组 t2=(10,)
注意:如果定义的元组只有一个数据,那么这个数据后面也好添加逗号,否则数据类型为唯一的这个数据的数据类型
t2=(10,) print(type(t2))#tuple t3=(20) print(type(t3))#int t4=('he11o') print(type(t4))#str
三.元组的常见操作
元组数据不支持修改,只支持查找具体如下:
·按下标查找数据 tuple1 ('aa','bb','cc','bb') 2 print(tuple1[0])#aa
index(0:查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index 方法相同。 tuple1=('aa','bb','cc','bb') print(tuple1.index('aa'))#0
count(0:统计某个数据在当前元组出现的次数。 tuple1 ('aa','bb','cc','bb') print(tuple1.count('bb'))#2
·Ien0:统计元组中数据的个数。 tuple1 ('aa','bb','cc','bb') print(len(tuple1))#4
字典
数据类型-⼜⻅dict
3.1 引子
我们学了列表,现在有个需求,把你们公司每个员工的姓名、年龄、职务、工资存到列表里,你怎么存?
staff_list = [ ["Alex",23,"CEO",66000], ["",24,"",4000], ["",26,"",40000], # [xxx,xx,xx,xxx] # [xxx,xx,xx,xxx] # [xxx,xx,xx,xxx] ]
这样存没问题,不过你要查一个人的工资的话, 是不是得把列表遍历一遍
for i in staff_list: if i[0] == '': print(i) break
但假如你公司有2万人,如果你要找的黑姑娘正好在列表末尾,那意味着你要遍历2万次,才能找到这个信息。列表越大,查找速度越慢。
3.2 dict 定义
字典,字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标,后期无论数据如何变化,只需要按照对应的键的名字查找数据即可。
{key1:value1, key2:value2}
info = { "name":"Alex Li", "age" : 26 } key -> value
:号左边是key,右边是value
字典特点: 符号为大括号 数据为键值对形式出现 各个键值对之间用逗号隔开
特性
1. key-value结构
2. key必须为不可变数据类型(字符串、数字)、必须唯一
3. 可存放任意多个value、可修改、可以不唯一
4. 无序, ordered_dict
5. 查询速度快,且不受dict的大小影响,至于为何快?我们学完hash再解释。
3.3 增加操作
写法:字典序列[key)=值 注意:1.如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。 2.字典为可变类型
dict1 {'name':'Tom','age':20,'gender':''} dict1['name']'Rose' #结果:{'name':'Rose','age':20,'gender':'男'} print(dict1) dict1['id']=110 {'name':'Rose','age':20,'gender':'''id':110} print(dict1)
3.4 删除操作
·del()/del:删除字典或删除字典中指定键值对。 dict1 {'name':'Tom','age':20,'gender':'' del dict1['gender'] #结果:{'name':Tom','age':20} print(dict1) clear():清空字典
3.5 修改操作
dic['key'] = 'new_value' # key'new_value'value
3.6 查操作
dic['key'] #返回字典中key对应的值,若key不存在字典中,则报错; dic.get(key,default None) #返回字典中key对应的值,若key不存在字典中,则返回 default的值(default默认为None) 'key'in dic#若存在则返回True,没有则返回False dic.keys() #返回一个包含字典所有KEY的列表; dic.values() #返回一个包含字典所有value的列表; dic.items() 返回一个包含所有(键,值)元组的列表; 并k,V2个变量 >>> for k,v in dic.items(): print(k,v) A1ex[23,'CE0',66000] 黑姑娘[24,·行政',4000] 佩奇【26,·讲师',40000]
3.7 循环
遍历字典的key
dict1={'name':Tom','age':2o,‘gender':‘男') for key in dict1.keys(): print(key) C:Users\黑马程序员\AppData\Local\Programs\Python\Python37 python3.exe name age gender Process finished with exit code 0
遍历字典的value
dict1 {'name':'Tom','age':20,'gender':''} for value in dict1.values(): print(value) C:\Users\黑马程序员\AppData\Local\Programs\Python\Python.37\python3.eXe Tom 20 男 Process finished with exit code 0
遍历字典的元素
dict1 {'name':'Tom','age':20 'gender':'' for item in dict1.items(): print(item) C:\Users\黑马程序员\AppData\Local\Programs\Python\Python37八python3.exe ('name','Tom') ('age',20) ('gender','男) Process finished with exit code 0
遍历字典的键值对
4.4遍历字典的键值对 dict1 ={'name':'Tom','age':20,'gender':'' for key,value in dict1.items(): print(f'{key}{value}')
3.8 求长度
len(info) # len()方法可同时⽤于列表、字符串
解释器自带函数
3.9 练习题
1.生成一个包含100个key的字典,每个value的值不能一样2.{'k0': 0,'k1': 1,'k2': 2,‘k3': 3, ‘k4': 4, 'k5': 5,‘k6': 6,‘k7': 7,‘k8': 8, ‘k9': 9} 请把这个dict中key大于5的值value打印出来。 3. 把题2中value是偶数的统一改成-1 4. 请设计一个dict,存储你们公司每个人的信息,信息包含至少姓名、年龄、电话、职位、工资,并提供一个简单的查找接口,用户按你的要求输入要查找的人,你的程序把查到的信息打印出来
集合
一.创建集合
创建集合使用}或set(),但是如果要创建空集合只能使用set(),因为)用来创建空字典。 s1={10,20,30,40,50} print(s1) s2={10,30,20,10,36,40,30,50} print(s2) s3 set('abcdefg') print(s3) s4 set() print(type(s4))#set s5={} print(type(s5)) dict
二.集合常见操作方法
2.1增加数据
add(),追加的数据是单一数据。
add() s1={10,20) s1.add(100) s1.add(10) print(s1)#{100,10,20} 因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进行任何操作.
update(),追加的数据是序列。
s1={10,20 s1.update(100) #报错 s1.update([100,200]) s1.update('abc')
2.2删除数据
remove(),删除集合中的指定数据,如果数据不存在则报错。
s1={10,20} s1.remove(10) print(s1) s1.remove(1)#报错 print(s1)
discard0,删除集合中的指定数据,如果数据不存在也不会报错。
s1={10,28) s1.discard(10) print(s1) s1.discard(10) print(s1)
pop(),随机删除集合中的某个数据,并返回这个数据。
s1={16,20,30,40,50} del_num s1.pop() print(del_num) print(s1)
查找数据
in:判断数据在集合序列 not in:判断数据不在集合序列
s1={10,20,30,40,50) print(10 in s1) print(10 not in s1)
格式化输出
格式化符号
格式化输出
我的名字是X,今年Y岁了,体重Z斤,学号是S
print("我的名字是%s,今年%d岁了,体重%.2f斤,学号是%03d" % (name, age, weight, stu_id))
f-字符串
格式化字符串除了%s,还可以写为f'{表达式}
print(f"我的名字是{name},今年{age}岁了,体重{weight}斤,学号是{stu_id}")
pytho3.6之后新增的功能,比%s更高效
转义字符
\n
换行
\t
制表符,一个tab键(4个空格)的距离
print的结束符
print("hello", end="\n")
print("world", end="\t")
print("hello", end="...")
print("world", end="XXXX")
默认为 end="\n"),可以更换
读取用户输⼊
若你的程序要接收用户指令,可以⽤input语法:
input("提示信息")
name = input("What is your name?")
print("Hello " + name )
输入的特点
当程序执行到 input ,等待用户输入,输入完成之后才继续向下执行。
在Python中, input接收用户输入后,一般存储到变量,方便使用。
在Python中,input 会把接收到的任意用户输入的数据都当做字符串处理。
执⾏脚本就会发现,程序会等待你输⼊姓名后再往下继续走。 可以让⽤户输入多个信息,如下
name = input("What is your name?") age = input("How old are you?") hometown = input("Where is your hometown?") print("Hello ",name , "your are ", age , "years old, you came from",hometown)
执⾏结果
What is your name?Alex Li How old are you?22 Where is your hometown?ShanDong Hello Alex Li your are 22 years old, you came from ShanDong
注意,input()方法接收的只是字符串,即使你输⼊的是数字,它也会按字符串处理
转换数据类型
一.转换数据类型的作用
问:input()接收用户输入的数据都是字符串类型,如果用户输入1,想得到整型该如何操作?
答:转换数据类型即可,即将字符串类型转换成整型。
二.转换数据类型的函数
转换数据类型的函数
推导式
目标
列表推导式
作用:用一个表达式创建一个有规律的列表或控制一个有规律列表。列表推导式又叫列表生成式。
需求: 创建一个0-10的列表。
把原代码去掉所有标点符号,缩进,换行等
列表推导式实现:
list1 = [i for i in range(10)] print(list1)
if实现
list1 = [i for i in range(10) if i % 2 == 0] print(list1)
需求:创建列表如下:[(1, 0), (1, 1), (1, 2), (2, θ), (2, 1), (2, 2)]
list1 = [(i, j) for i in range(1, 3) for j in range(3)] print(list1)
字典推导式
思考:如果有如下两个列表: list1 = ['name', 'age', 'gender'] list2 = ['Tom', 20, 'man'] 如何快速合并为一个字典?
答:字典推导式字典推导式作用:快速合并列表为字典或提取字典中目标数据。
1. 创建一个字典:字典key是1-5数字,value是这个数字的2次方。
dict1 = {i: i**2 for i in range(1, 5)} print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16}
2.将两个列表合并为一个字典
list1 = ['name', 'age', 'gender'] list2 = ['Tom', 20, 'man'] dict1 = {list1[i]: list2[i] for i in range(len(list1))} print(dict1)
.如果两个列表数据个数相同,len统计任何一个列表的长度都可以. 如果两个列表数据个数不同,len统计数据多的列表数据个数会报错: len统计数据少的列表数据个数不会报错
3. 提取字典中目标数据
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99} # 需求:提取上述电脑数量大于等于200的字典数据 count1 = {key: value for key, value in counts.items() if value >= 200] print(count1) # {'MBP': 268, 'DELL': 201}
集合推导式
需求:创建一个集合,数据为下方列表的2次方。
list1 = [1, 1, 2] set1 = {i ** 2 for i in list1} print(set1) # {1, 4}
集合有数据去重功能
总结
# 列表推导式[xx for xx in range()] #字典推导式{xx1: xx2 for ... in ...} 集合推导式{xx for xx in ...}
运算符
计算机可以进⾏行的运算有很多种,可不只加减乘除这么简单,运算按种类可分为算数运算、比较运算、逻辑运算、赋值运算、成员运算、身份运算、位运算,今天我们暂只学习算数运算、比较运算、逻辑运算、赋值运算、成员运算
算术运算符
以下假设变量量:a=10,b=20
运算符
比较运算符
以下假设变量量:a=10,b=20
注意:<>在python3⾥已经取消了,仅在py2⾥有效
赋值运算符
以下假设变量量:a=10,b=20
逻辑运算
以下假设变量量:a=10,b=20
注意了还可以多个or 或and 拼在⼀起
or的优先级更高。注意,我画的红线,只要遇到or 就相当于把公式分成2半了,括号⾥的⼦公式会先计算出来结果,再跟其它的值对比。 因为括号的优先级更高
成员运算
只有in, not in 2种, ⽤用来测试数据中是否包含了⼀系列的成员
全宇宙最好⽤的代码编辑器
Pycharm
创建项⽬
注册完成后启动,会让你先创建⼀个项⽬目,其实就是⼀个文件夹,我们以后的代码都存在这⾥
创建文件目录
你以后写的项⽬目可能有成百上千个代码⽂文件 ,全放在⼀起可不不好,所以一般把同样功能的代码放在⼀个目录,我们现在以天为单位,为每天的学习创建⼀个目录day1,day2,day3…这样
创建代码文件
执⾏代码
代码调试
想不想看代码⼀步步的执⾏过程?⽐如想看每次循环某个变量有没有变化,总是print太low了了,试试pycharm ⽜逼的debug功能吧
格式化打印
现有⼀一练习题需求,问用户的姓名、年龄、工作、爱好 ,然后打印成以下格式
------------ info of Alex Li ----------- Name : Alex Li Age : 22 job : Teacher Hobbie: girl ------------- end -----------------
你怎么实现呢?你会发现,用字符拼接的方式很难实现这种格式的输出,所以⼀起来学⼀下新姿势 你只需要简单的在字符串⾥引⽤你外部的变量就可以啦。。。。。
语法
name = "Alex" age = 22 print( f"hello my name is {name}, I am {age} old..")
注意字符串开头要加上f ,才可以在⾥面⽤{} 来引⽤用外部变量
这样实现上⾯面的需求就很简单啦
name = input("Name:") age = input("Age:") job = input("Job:") hobbie = input("Hobbie:") info = f''' ------------ info of {name} ----------- Name : {name} Age : {age} job : {job} Hobbie: {hobbie} ------------- end -----------------
流程控制之if...else...
假如把写程序比做⾛路,那我们到现在为止,一直⾛的都是直路,还没遇到过分叉⼝口,想象现实中,你遇到了分叉⼝,然后你决定往哪拐必然是有所动机的。你要判断那条岔路是你真正要⾛的路,如果我们想让程序也能处理这样的判断怎么办? 很简单,只需要在程序⾥里预设⼀一些条件判断语句,满足哪个条件,就⾛走哪条岔路。这个过程就叫流程控制。基本上在各个语⾔言中,都是⽤用语法if…else…来实现,可分为单分⽀、双分⽀、多分⽀
单分⽀
双分⽀
缩进
你会发现,上面的if代码⾥,每个条件的下⼀⾏都缩进了4个空格,这是为什么呢?这就是Python的⼀一大特色,强制缩进,目的是为了让程序知道,每段代码依赖哪个条件,如果不通过缩进来区分,程序怎么会知道,当你的条件成立后,去执行哪些代码呢?
在其它的语⾔言⾥里里,⼤大多通过{} 来确定代码块,⽐比如C,C++,Java,Javascript都是这样,看⼀一个JavaScript代码的例⼦
var age = 56 if ( age < 50){ console.log("还能折腾") console.log('可以执⾏多⾏代码') }else{ console.log('太⽼了') }
在有{} 来区分代码块的情况下,缩进的作⽤就只剩下让代码变的整洁了。Python是⻔超级简洁的语⾔,发明者定是觉得⽤{} 太丑了,所以索性直接不用它,那怎么能区分代码块呢?答案就是强制缩进。
Python的缩进有以下几个原则:
顶级代码必须顶⾏写,即如果⼀行代码本身不依赖于任何条件,那它必须不能进⾏任何缩进
同⼀级别的代码,缩进必须⼀致
官⽅建议缩进⽤4个空格,当然你也可以⽤2个,如果你想被⼈笑话的话。
多分⽀
回到流程控制上来,if…else …可以有多个分⽀条件
写个猜年龄的游戏吧
age_of_oldboy 48 guess int(input(">>:")) if guess age_of_oldboy print("猜的太大了,往小里试试..") elif guess age_of_oldboy print("猜的太小了,往大里试试...") else: print("恭喜你,猜对了..")
上⾯面的例⼦,根据你输⼊的值不同,会最多得到3种不同的结果
再实现⼀下⾯这个需求吧,写⼀段程序,读取⽤户输⼊的⼯资,根据⼯资多少打印相应的⽂字
你的⼯资多少决定了你的心态
月薪1000:⽼板,我是你爹。 月薪2000:⽼板,wqnmlgbxxxx 月薪5000:⽼板脑⼦子有坑,背后说坏话。 ⽉薪1万:⽼板说的有有点问题,但我不说话。 月薪2万:⽼板说啥就是啥吧,给钱就⾏。 ⽉薪3万:⽼板说什么都是对,如果有⼈人错了,那⼀定是我。 ⽉薪5万:996就像呼吸⼀一样自然。 月薪10万:公司就是我家。
这⾥有个问题,就是当我输⼊25000的时候 ,它打印的结果是“⽼板说啥就是啥吧,给钱就⾏行行”, 但是25000 明明也⼤于第条件elif salary>=10000: 呀, 为什么不同时执⾏后⾯面的呢?这是因为代码是从上到下依次判断,只要满⾜⼀个,就不会再往下⾛啦,这⼀点⼀定要清楚呀!
三目运算符
三目运算符也叫三元运算符或三元表达式
条件成立执行的表达式 if 条件 else 条件不成立执行的表达式
例子:
for 循环
我们已经学过了⽤用if..else...进⾏程序的流程控制,也写了猜年龄的⼩游戏。 可是每次启动后只能猜⼀次, 如果我希望⽤用户猜不对时可以重复猜,可怎么办? 哈,那就需要⽤用到接下来循环的知识了。
1.1 语法
for i in range(10): print(i)
上⾯代码,会从0-9,共循环10次,这个range(10),其实是相当于产生了一个从0到9的列表,每循环⼀次,就会把列表⾥的下⼀个元素取出来给临时变量i.
执⾏结果:print( list(range(10)) ) # 可以验证range(10) 就是产⽣生了一个列表
1.2 循环猜年龄
需求: 最多允许猜三次,猜对了就退出程序
black_gf_age = 24 for i in range(3): guess = int(input("猜猜姑娘多⼤了>>:")) if guess > black_gf_age: print("猜的太大了,往⼩⾥试试...") elif guess < black_gf_age: print("猜的太小了,往大⾥试试...") else: exit("恭喜你,猜对了...") # 退出程序
1.3打印奇偶数
打印50-100间的奇数
for i in range(50, 100): # 可以定义区间 if i % 2 == 1: print(i)
1.4 循环嵌套
⼀栋楼有5层,每层8间屋⼦,要求你把本楼所有的房间号打印⼀一遍, 格式“1层-104”, “2层-205“
for i in range(1,6): for j in range(1,9): print(f"{i}层-{i}0{j}室")
for...else
语法
for临时变量in序列: 重复执行的代码 else: 循环正常结束之后要执行的代码
所谓else指的是循环正常结束之后要执行的代码,即如果是break:终止循环的情况,else下方缩进的代码将不执行。
因为continue:是退出当前一次循环,继续下一次循环,所以该循环在continue控制下是可以正常结束的,当循环结束后,则执行了else缩进的代码。
break & continue
2.1 break & continue
像上边循环嵌套⼩节那个打印楼层的⼩程序,需求改了, 遇到第3层时,不打印任何房间号,其它层都打印。
continue
continue的语法作⽤用是, 只要程序一遇到continue, 本次循环就不继续了,直接进⼊下⼀次循环
for i in range(1,6): for j in range(1,9): if i == 3: continue # 跳过本次循环,继续下次循环 print(f"{i}层-{i}0{j}室")
break
break的语法作⽤是,只要程序遇到break, 就会结束当前这个循环, 注意如果是多层嵌套循环,只结束当前这⼀层的循环。
for i in range(1, 6): for j in range(1, 9): if i == 3: print("不⾛3层.......") continue # 跳过本次循环,继续下次循环 if i == 4 and j == 4: # 遇到404 print("遇到鬼屋404了了,不不再继续了") break # 结束当前循环, 注意只会结束第2层这个小循环。 print(f"{i}层-{i}0{j}室")
2.2 打印三⻆角形
打印这样的形状
* ** *** **** ***** **** *** ** *
解题思路,10次循环,前5次打印i * "*" , 后5次打印(10-i) * "*"
n = 10 for i in range(n): if i < 5: print(i*"*") else: print( (n-i) * "*")
while 循环
与for必须指定循环多少次不一样的是, while 循环的次数可以是不定的,只要条件满⾜就可以永远循环下去
3.1 语法
while 条件: # 只要条件为真, 就会不断的循环 print(xxxxx)
死循环
count = 0 while True: # 条件永远为真 print("第{count}次循环....") count += 1
循环10次
这样就形成了跟for i in range(10)⼀样的效果
count = 0 while count < 10: print("第{count}次循环....") count += 1
3.2 ⽤while 实现循环猜年龄
需求: 允许用户猜3次,若还不对,告诉他,你真笨,还想继续猜么? 如果用户选择yes, 就让他继续,如果选择no, 就退出。
black_gf_age = 25 count = 0 while True: count += 1 if count <= 3: guess = int(input("猜⿊黑姑娘多大了>>:")) if guess > black_gf_age: print("猜的太大了,往⼩⾥试...") elif guess < black_gf_age: print("猜的太小了,往⼤⾥试试...") else: exit("恭喜你,猜对了...") # 退出程序 else: choice = input("猜了3次还不对,真是笨呀,还玩么? [y/Y or n/N]").strip() if len(choice) == 0 : continue # 不能写空值 if choice in ("y","Y"): count = 0 elif choice in ("n","N"): exit("bye.") else: print("请输⼊正确的选项...")
while---else
语法
while条件: 条件成立重复执行的代码 else: 循环正常结束之后要执行的代码
因为continue是退出当前一次循环,继续下一次循环,所以该循环在continue:控制下是可以正常结束的,当循环结束后,则执行了else缩进的代码。
京牌摇号小程序
需求:
1. 允许⽤用户最多选3次
2. 每次放出20个⻋车牌供⽤户选择
3. 京[A-Z]-[xxxxx], 可以是数字和字⺟在组合
想实现这个程序 ,有2个问题要解决:
1. 如果实现输出随机值
2. 随机值需限定在⼤大写字⺟母,和数字范围内,不能有其它特殊字符。
这就要⽤到一些超纲知识, random模块和string模块。 Python的模块库是个宝藏,想实现任何功能它都有现成的模块供你调⽤
4.1 random模块
可以产⽣生指定范围内的随机数、字符串等
>>> import random # 导⼊入random模块 >>>random.choice("abcdefghi") # 参数也可以是⼀个列表 'd' >>> s = "abcdefghijklmn" >>> random.sample(s,3) # 从数据源s中随机取出3个值 ['b', 'a', 'k'] >>> random.randint(1,100) # 打印⼀个随机数 79
4.2 string 模块
>>> import string # 导⼊入string模块 >>> string.ascii_letters 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >>> string.ascii_uppercase 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # ⼤写字⺟ >>> string.ascii_lowercase # ⼩写字⺟母 'abcdefghijklmnopqrstuvwxyz' >>> string.punctuation # 打印特殊字符 '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' >>> string.digits # 打印数字 '0123456789'
4.3 代码实现
import random import string car_num_sample = string.digits+string.ascii_uppercase print(random.sample(car_num_sample,5)) count = 3 while count > 0 : count -= 1 num_list = [] for i in range(20): second_letter = random.choice(string.ascii_uppercase) car_num = f"京{second_letter}-{ ''.join(random.sample(car_num_sample,5)) }" num_list.append(car_num) print(i, car_num) choice = input("choice:").strip() if choice in num_list: exit(f"恭喜你选购成功,您的新⻋车牌是{choice}") else: print(f"未选中, 还有{count}次机会")
综合练习
年会抽奖程序
张三科技有限公司有300员⼯工,开年年会抽奖,奖项如下:
一等奖 3名, 泰国5⽇日游
二等奖6名,Iphone⼿手机
三等奖30名,避孕套⼀一盒
规则:
1. 共抽3次,第⼀次抽3等奖,第2次抽2等奖,第3次压抽1等奖
2. 每个员⼯工限中奖⼀一次,不能重复
解题思路:
1. ⽣成⼀一个员⼯列表,⽤random模块从⾥面取随机值
2. 取完值之后,立刻从员⼯⼤列表⾥把中奖⼈删掉,即可防⽌其再次中奖
⼆进制运算
计算机是靠电流驱动的,科学家们是如何做到让电流能理解数字、文字、图片等人类语言的呢?科学家发现,可以通过控制电压把电流分成高电压、低电压,高电压可以代表一种状态,低电压又可代表另一状态。这样计算机就可以识别2种状态了。就像一个灯泡,开灯可以代表1,关灯可以代表0,就是2种状态。如果多个灯泡的组合,就可以表达更多的值啦。这跟数学里的一个叫二进制的东东很像,二进制只有0和1两个数,想表达更大的值 就往左补位,多个0101010就可以表达更大的值 啦。二进制是逢2进1,跟我们用的十进制逢10进1一个原理。 于是科学家们,就用2进制做为计算机可识别的最底层语言啦。
逢二进一,十进一
4.1 ⼆进制与10进制转换
刚才我们已经发现,二进制的第n位代表的十进制值都刚好遵循着2的n次方这个规律。2 https://book.apeland.cn/details/35/
字符编码
5.1 引⼦
通过上一节讲的二进制的知识,大家已经知道计算机只认识二进制,生活中的数字要想让计算机理解就必须转换成二进制。十进制到二进制的转换只能解决计算机理解数字的问题,那么文字要怎么让计算机理解呢?于是我们就选择了一种曲线救国的方式,既然数字可以转换成十进制,我们只要想办法把文字转换成数字,这样文字不就可以表示成二进制了么?
可是文字应该怎么转换成数字呢?就是强制转换啊,简单粗暴呀。我们自己强行约定了一个表,把文字和数字对应上,这张表就相当于翻译,我们可以拿着一个数字来对比对应表找到相应的文字,反之亦然。
5.2 ASCII编码
这张表就是计算机显示各种文字、符号的基石呀
ASCIl (American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉工字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。由于计算机是美国人发明的,因此,最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII 编码,比如大写字母 A的编码是 65,小写字母z 的编码是122。后128个称为扩展ASCII码。
那现在我们就知道了上面的字母符号和数字对应的表是早就存在的。那么根据现在有的一些十进制,我们就可以转换成二进制的编码串。比如
提问:假如我们要打印两个空格一个对勾写作二进制就应该是0011111011,但是问题来了,我们怎么知道从哪儿到哪儿是一个字符呢?
论断句的重要性与必要性:之前在网上看到个新闻,讲是个小偷在上海被捕时高喊道: “我一定要当上海贼王!”正是由于这些字符串长的长,短的短,写在一起让我们难以分清每一个字符的起止位置,所以聪明的人类就想出了一个解决办法,既然一共就这255个字符,那最长的也不过是11111111八位,不如我们就把所有的二进制都转换成8位的,不足的用0来替换。这样一来,刚刚的两个空格一个对勾就写作000000000000000011111011,读取的时候只要每次读8个字符就能知道每个字符的二进制值啦。
5.3 计算机容量单位
在这里,每一位0或者1所占的空间单位为bit(比特),这是计算机中最小的表示单位每8个bit组成一个字节,这是计算机中最小的存储单位(毕竟你是没有办法存储半个字符的)orz~
5.4 GB2312 & GBK
英文问题是解决了,我们中文如何显示呢?美国佬设计ASSCII码的时候应该是没考虑中国人有一天也能用上电脑,所以根本没考虑中文的问题,上世界80年代,电脑进入中国,把砖家们难倒了,妈的你个一ASSCII只能存256个字符,我常用汉字就几千个,怎么玩? ??勒紧裤腰带还苏联贷款的时候我们都挺过来啦,这点小事难不到我们,既然美帝的ASCII不支持中文,那我们自己搞张编码表不就行了,于是我们1980年设计出了GB2312编码表,长成下面的样子。一共存了6763个汉字。
这个表格比较大,像上面的一块块的文字区域有72个,这导致通过一个字节是没办法表示一个汉字的(因为一个字节最多允许256个字符变种,你现在6千多个,只能2个字节啦,2**16=65535个变种)。有了gb2312,我们就能愉快的写中文啦。 但我们写字竟然会出现中英混杂的情况,比如“我是路飞学城,我的英文名叫Luffycity.”, 这种你怎么办?这就要求你必须在gb2312里同时支持英文,但是还不能是2个字节表示一个英文字母。人家ASCIl用一个字符,你用2个,那一个2mb大小的英文文档只要一改编码,就立刻变成4mb,太坑爹,中国人你有钱也不能这么造呀。 所以中国砖家们又通过神奇手段兼容了ASSCII, 即遇到中文用2个字节,遇到英文直接用ASCII的编码。怎么做到的呢?如何区别连在一起的2个字节是代表2个英文字母,还是一个中文汉字呢?中国人如此聪明,决定,如果2个字节连在一起,且每个字节的第1位(也就是相当于128的那个2进制位)如果是1,就代表这是个中文,这个首位是128的字节被称为高字节。 也就是2个高字节连在一起,必然就是一个中文。你怎么如此笃定?因为0-127已经表示了英文的绝大部分字符, 128-255是ASCII的扩展表,表示的都是极特殊的字符,一般没什么用。所以中国人就直接拿来用了。自1980年发布gb2312之后,中文一直用着没啥问题,随着个人电脑进入千家万户,有人发现,自己的名字竟然打印不出来,因为起的太生僻了。于是1995年,砖家们又升级了gb2312,加入更多字符,连什么藏语、维吾尔语、日语、韩语、蒙古语什么的统统都包含进去了,国家统一亚洲的野心从这些基础工作中就可见一斑哈。这个编码叫GBK, 一直到现在,我们的windows电脑中文版本的编码就是GBK.
5.5 编码战国时代
解决乱码: 1.中国电脑上装日本 shift_jis 2. 让日本 游戏厂商,用gbk编码中国人在搞自己编码的同时,世界上其它非英语国家也得用电脑呀,于是都搞出了自己的编码,你可以想得到的是,全世界有上百种语言,日本把日文编到ShiftJIS里,韩国把韩文编到Euc-kr里, 各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。之前你从玩个日本游戏,往自己电脑上一装,就显示乱码了。 这么乱极大了阻碍了不同国家的信息传递,于是联合国出面,发誓要解决这个混乱局面。因此,Unicode应运而生。 Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode 2-4字节 已经收录136690个字符,并还在一直不断扩张中.. Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。 现代操作系统和大多数编程语言都直接支持Unicode。Unicode有2个特点:1. 支持全球所有语言2. 可以跟各种语言的编码自由转换,也就是说,即使你gbk编码的文字,想转成unicode很容易。 为何unicode可以跟其它语言互相转换呢?因为有跟所有语言都有对应关系哈,这样做的好处是可以让那些已经用gbk或其它编码写好的软件容易的转成unicode编码,利于unicode的推广。下图就是unicode跟中文编码的对应关系
5.6 UTF-8
新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,由于计算机的内存比较大,并且字符串在内容中表示时也不会特别大,所以内容可以使用unicode来处理,但是存储和网络传输时一般数据都会非常多,那么增加1倍将是无法容忍的!!! 为了解决存储和网络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对unicode字符进行转换,以便于在存储和网络传输时可以节省空间!UTF-8: 使用1、2、3、4个字节表示所有字符;优先使用1个字节、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个 UTF-16: 使用2、4个字节表示所有字符;优先使用2个字节,否则使用4个字节表示。 UTF-32: 使用4个字节表示所有字符;总结: UTF是为unicode编码设计的一种在存储和传输时节省空间的编码方案。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:
从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。搞清楚了ASCIl、 Unicode和UTF-8的关系,我们就可以总结一下现在计算机系统通用的字符编码工作方式: 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。
5.7 常⽤用编码介绍⼀一览表
5.8 Py2 Vs Py3编码
python生下来的时候 还没有unicode&utf-8,所以龟叔选用的默认编码只能是ASCIl, 一直到py2.7,用的还是ASCII,导致Py默认只支持英文,想支持其它语言,必须单独配置。
直接写中文执行会报错的。需在文件开头声明文件的编码才能写中文
再执行就不会有错了。不过注意如果你的电脑 是windows系统,你的系统默认编码是GBK,你声明的时候要声明成GBK,不能是utf-8, 否则依然是乱码,因为gbk自然不认识utf-8.在Py2里编码问题非常头疼,若不是彻底理解编码之间的各种关系,会经常容易出现乱码而不知所措。到了Py3推出后,终于把默认编码改成了unicode,同时文件存储编码变成了utf-8,意味着,不用任何声明,你就可以写各种语言文字在你的Python程序里。从此,程序们手牵手过上了快乐的生活。
秒懂16进制
16进制,英文名称Hexadecimal(简写Hex),在数学中是一种逢16进1的进位制。一般用数字0到9和字母A到F (或a-f)表示,其中:A-F表示10-15,这些称作十六进制数字,比如十进制13用16进制表示是D,28用16进制是1C。
16进制在计算、机领域应用普遍,常见的有html\css的颜色表、mac地址、字符编码等都用16进制来表示。这是因为将4个位元(Bit)化成单独的16进制数字不太困难。1字节可以表示成2个连续的16进制数字。可是,这种混合表示法容易令人混淆,因此需要一些字首、字尾或下标来显示,在C语言、C++、Shell、Python、Java语言及其他相近的语言使用字首"0x"来标示16进制,例如“Ox5A3"代表1443。
⼀、不同字符编码间的转换
1.1 GBK编码的字符如何转成utf-8存储?
上节课我们讲过, windows系统的默认编码是GBK,如果你把一段在windows系统上用gbk编码的字符发送到mac电脑上, mac默认编码是utf-8,那这段文字是乱码显示的。如何实现在mac上正常显示这段gbk文本呢?
为何要先转成Unicode呢?
若你认真听了昨天的编码课,你应该知道,gbk和utf-8之间没任何关系的,就跟中文跟日语没关系一样。而Unicode是和所有的编码都有映射关系,所以可以先转成unicode,再转成utf-8
编码与解码
1.任意编码转换成unicode的过程,都叫解码
把内存里的数据存到文件里,需要编码过程
2.把unicode转换成任意编码的过程,都叫编码
一般把文件内容读到内存时,需要进行解码过程
更详细例⼦
bytes字节类型是用16进制表示的,像这样\xe8 这样2个16进制数是代表一个字节(因为一个16进制是占4位,2个就是8位,共1个字节啦) 0-15
1.2 字节类型是什么东东?
你可以理解为,字节类型就是2进制格式,只不过为了易于理解和人类肉眼计算,是用16进制来表示而已。 路飞的gbk编码的bytes数据是 b'\xc2\xb7\xb7\xc9' 如果转成2进制是10000100011p1111010100101 很显然,一堆2进制是很难理解的,用16进制来表示,会比较容易计算。
1.3为何编码后要转成bytes字节类型?
为了防止显示乱码,我的mac电脑上,不支持gbk编码,如果直接以原格式打印,就会乱码。但用字节形式表示,就没这个问题了。
下⾯面⽤用py2来演示下乱码效果
这是因为,在python2上,print时没有打印字节码,而是尝试用utf-8的编码去解释这段gbk字符,自然就乱了。
二、文件操作
文件操作的作用
总结:文件操作的作用就是把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力。
2.1 python操作文件流程
用word操作一个文件的流程如下:
1. 找到文件
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,
语法如下:
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。 mode:设置打开文件的模式(访问模式):只读、写入、追加等。
2. 读或修改
基础访问模式
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 r+ 打开一个文件用于读写。文件指针将会放在文件的开头。 rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
r
r及其附属模式,如果文件不存在,则报错
r+: r没有该文件则报错;文件指针在开头,所以能读取出来数据
w
w及其附属模式,如果文件不存在,则创建新文件
w+:没有该文件会新建文件:w特点:文件指针在开头,用新内容覆盖原内容
a
a及其附属模式,如果文件不存在,则创建新文件
a+:没有该文件会新建文件:文件指针在结尾,无法读取数据(文件指针后面没有数据)
创建或打开文件
追加模式
用python操作文件也差不多:
不过有一点跟人肉操作word文档不同,就是word文档只要打开了,就即可以读、又可以修改。 但Python比较变态,只能以读、创建、追加 3种模式中的任意一种打开文件,不能即写又读。
文件打开模式(混合模式)
其实我一直像你隐瞒,因为怕你觉得复杂。打开文件其实还有3种混合模式 w+写读,这个功能基本没什么意义,它会创建一个新文件,写一段内容,可以再把写的内容读出来,没什么卵用。 r+读写,能读能写,但都是写在文件最后,跟追加一样 a+追加读,文件一打开时光标会在文件尾部,写的数据全会是追加的形式
r+模式
因为默认就是往文件 尾部写
修改文件
尝试直接以r+模式打开文件,默认会把新增的内容追加到文件最后面。但我想要的是修改中间的内容怎么办?为什么会把内容添加到尾部呢?(最新测试r+会从头覆盖,测试代码如下)
问:为什么原有数据会被覆盖呢?
这是硬盘的存储原理导致的,当你把文件存到硬盘上,就在硬盘上划了一块空间,存数据,等你下次打开这个文件,seek到一个位置,每改一个字,就是把原来的覆盖掉,如果要插入,是不可能的,因为后面的数据在硬盘上不会整体向后移。所以就出现当前这个情况,你想插入,却变成了会把旧内容覆盖掉。
问:但是人家word, vim 都可以修改文件 呀,你这不能修改算个什么玩意?
我并没说就不能修改了,你想修改当然可以,就是不要在硬盘上修改,把内容全部读到内存里,数据在内存里可以随便增删改查,修改之后,把内容再全部写回硬盘,把原来的数据全部覆盖掉。vim word等各种文本编辑器都是这么干的。
问:说的好像有道理,但你又没看过word软件的源码,你凭什么这么笃定?
哈哈,我不需要看源码,硬盘 的存储原理决定了word必须这么干,不信的话,还有个简单的办法来确认我说的,就是用word or vim读一个编辑一个大文件,至少几百MB的,你 会发现,加载过程会花个数十秒,这段时间干嘛了? cpu去玩了?去上厕所啦?当然不是,是在努力把数据从硬盘上读到内存里。
问:但是文件如果特别大,比如5个GB,读到内存,就一下子吃掉了5GB内存,好费资源呀,有没有更好的办法呢?
如果不想占内存,只能用另外一种办法啦,就是边读边改,什么意思? 不是不能改么?是不能改原文件,但你可以打开旧文件的同时,生成一个新文件呀,边从旧的里面一行行的读,边往新的一行行写,遇到需要修改就改了再写到新文件,这样,在内存里一直只存一行内容。就不占内存了。但这样也有一个缺点,就是虽然不占内存,但是占硬盘,每次修改,都要生成一份新文件,虽然改完后,可以把旧的覆盖掉,但在改的过程中,还是有2份数据 的。
问:还有更好的方式么?
有完没完?没了。
2.9 占硬盘方式的文件修改代码示例
上⾯面的代码,会⽣生成⼀个修改后的新文件 ,原文件不动,若想覆盖原文件
二进制模式操作文件
上面操作的只是文本文件,但是如果遇到视频呀、图片呀,你直接打开的话会报错
为何报utf-8不能解码的错?是因为,open()有个encoding参数,默认是None,是用来告诉解释器,要操作的这个文件 是什么编码。不填的话,就用解释器默认编码,即utf-8。
如果你是一个gbk编码的文件,就必须指定 encoding-gbk
但是像图片、视频,是有自己特殊的编码的,而非什么unicodelutf-8这样的文本编码。所以要操作这样的文件,你用utf-8什么的去解,自然会报错。
如何处理图片、视频文件呢?
可以用2进制模式打开文件
1.rb 2进制只读模式 2.wb 2进制创建模式,若文件已存在,则覆盖旧文件 3.ab 2进制追加模式,新数据会写到文件末尾
这样,你读出来的数据,就是bytes字节类型了,当然写进去的也必须是bytes格式了
读取函数
read()
文件对象.read(num) num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
readlines()
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
readline()
readline()一次读取一行内容。
只读模式
执行输出
seek()
用来移动文件指针
文件对象.seek(偏移量,起始位置) 起始位置: ·0:文件开头 .1:当前位置 .2:文件结尾
循环文件
数据源: 1. 马纤羽 深圳 17350 13744234523 2. 乔亦菲 广州 172 52 15823423525 3,罗梦竹北京175 49 18623423421 4. 刘诺涵 北京 170 48 18623423765 5, 岳妮妮深圳17754 18835324553 6,贺婉萱深圳174 52 18933434452 7,叶梓萱上海171 49 18042432324
输出
其它功能
3,文件备份
需求:用户输入当前目录下任意文件名,程序完成对该文件的备份功能(备份文件名为XX[备份]后缀,例如:test[备份].txt).
1. 接收用户输入的文件名
2. 规划备份文件名
提取目标文件后缀---- 找到名字中的点 -- 名字和后缀分离--最右侧的点才是后缀的点 -- 字符串查找某个子串rfind
组织新名字原名字 +[备份] + 后缀并 原名字就是字符串中的一部分子串 --切片「开始;结束;步长]
3,备份文件写入数据
4.文件和文件夹的操作
在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
1. 导入os模块
import os
2.使用 os 模块相关功能
os.函数名()
文件重命名
os.rename(目标文件名,新文件名)
文件夹同样适用
删除文件
os.remove(目标文件名)
创建文件夹
os.mkdir(文件夹名字)
删除文件夹
os.rmdir(文件夹名字)
获取当前目录
os.getcwd()
改变默认目录
os.chdir(目录)
获取目录列表
os.listdir(目录)
2.10 练习题-全局⽂文本检索替换
写一个脚本,允许用户按以下方式执行时,即可以对指定文件内容进行全局替换,且替换完毕后打印替换了多少处内容写完后的脚本调用方式:
python your_script.py old_str new_str filename
2.11练习题-用户登录认证程序
要求用户输入帐号密码进行登陆
用户账号信息保存在文件内
用户密码输入错误三次后锁定用户,下次再登录,检测到是这个被锁定的用户,则依然不允许其它登录,提示已被锁
三、综合实战-股票数据分析&处理
把以下股票数据存入stock_data.txt
开发程序对stock_data.txt进行以下操作:
1,程序启动后,给用户提供查询接口,允许用户重复查股票行情信息(用到循环)
2.允许用户通过模糊查询股票名,比如输入"啤酒",就把所有股票名称中包含"啤酒"的信息打印出来
3,允许按股票价格、涨跌幅、换手率这几列来筛选信息,比如输入"价格>50"则把价格大于50的股票都打印,输入"市盈率<50",则把市盈率小于50的股票都打印,不用判断等于。
思路提示:加载文件内容到内存,转成dict or list结构,然后对dict or list 进行查询等操作。这样以后就不用每查一次就要打开一次文件了,效率会高。
程序启动后执行效果参考:
数据源已经帮你准备好了 stock_data.txt
函数编程
1.1 引⼦,函数编程的作⽤
你是一家公司的IT运维人员,现在老板让你写一个监控程序, 24小时全年无休的监控你们公司网站服务器的系统状况,当cpu\memory \disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码
上面的代码实现了功能,但即使是邻居老王也看出了端倪,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:
1. 代码重复过多,一个劲的copy and paste不符合高端程序员的气质
2,如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍
你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下
你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,心想,老王这个人真是不一般,突然对他的背景更感兴趣了,问老王,这些花式玩法你都是怎么知道的?老王亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲, “老夫,年少时,师从京西沙河淫魔银角大王",你一听“银角大王"这几个字,不由的娇躯一震,心想,真nb,怪不得代码写的这么6,这“银角大王”当年在江湖上可是数得着的响当当的名字,只可惜后期纵欲过度,卒于公元2019年,真是可惜了,只留下其哥哥孤守当年兄弟俩一起打下来的江山。此时你看着的老王离开的身影,感觉你儿子跟他越来越像了。。
函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求。函数在开发过程中,可以更高效的实现代码重用。
函数是什么?
函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在C中只有function,在Java里面叫做method。
定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
1. 减少重复代码
2. 使程序变的可扩展
3,使程序变得易维护
函数的使用步骤
第一步:定义函数
def函数名(参数): 代码1 代码2
第二步:调用函数
1函数名(参数) 注意: 1.不同的需求,参数可有可无。 2.在Pythont中,函数必须先定义后使用。
需求:复现ATM取钱功能.
1.搭建整体框架(复现需求)
print('密码正确登录成功') #显示"选择功能"界面 print('查询余额完毕') #显示“选择功能“界面 print('取了2000元钱') #显示"选择功能"界面
2. 确定“选择功能”界面内容
print('查询余额') print('存款') print('取款')
3. 封装"选择功能" 注意:一定是先定义函数,后调用函数。
#封装ATM机功能选项-- 定义函数 def select_func(): print('---请选择功能---') print('查询余额') print('存款') print('取款') print(--请选择功能--')
4.调用函数 在需要显示"选择功能"函数的位置调用函数。
def sel_func(): print("显示金额") print("存款") print("取款") print("恭喜您,登录成功") sel_func() print("您的余额为10000") sel_func() print("取款1000元") sel_func()
函数的注意事项
结论:
1,函数先定义后调用,如果先调用会报错
2.如果没有调用函数,函数里面的代码不会执行
3.函数执行流程***当调用函数的时候,解释器回到定义函数的地方去执行下方缩进的代码,当这些代码执行完,回到调用函数的地方维续向下执行定义函数的时候,函数体内部缩进的代码并没有执行
1.3 各种参数
形参变量
只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用程序代码后则不能再使用该形参变量
实参
实参可以是变量、任意数据类型、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先给实参赋值
函数的返回值作用
例如:我们去超市购物,比如买烟,给钱之后,是不是售货员会返回给我们烟这个商品,在函数中,如果需要返回结果给用户需要使用函数返回值。
def buy(): return'烟 #使用变量保存函数返回值 goods buy() print(goods)
函数外部的代码要想获取函数的执⾏结果,就可以在函数⾥return语句把结果返回
return 作用:退出当前函数导致return下方的所有代码(函数体内部)不执行
返回值return
函数外部的代码要想获取函数的执⾏结果,就可以在函数⾥return语句把结果返回
注意:函数在执行过程中只要遇到return语句,就会停止执行并返回结果, so也可以理解为return语句代表着函数的结束如果未在函数中指定return,那这个函数的返回值为None
·返回值作为参数传递
def test1(): return 50 def test2(num): print(num) #1,保存函数test1的返回值 result test1() #2.将函数返回值所在变量作为参数传递到tst2函数 test2(result) # 50
思考:如果一个函数如些两个return (如下所示),程序如何执行?
def return_num(): return 1,2 result return_num() print(result) #(1,2)
注意: 1. return a, b写法,返回多个数据的时候,默认是元组类型。 2.return后面可以连接列表、元组或字典,以返回多个值。
函数的参数
位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
注意:传递和定义参数的顺序及个数必须一致。
关键字参数(指定参数)
函数调用,通过"键=值"形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后
调用可以这样
但绝不可以这样
当然这样也不⾏
这样相当于给age赋值2次,会报错!
注意,参数优先级顺序是 位置参数>关键参数
缺省参数(默认参数)
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
看如下代码
发现country这个参数基本都是"CN",就像我们在网站上注册用户,像国籍这种信息,你不填写,默认就会是中国,这就是通过默认参数实现的,把country变成默认参数非常简单
这样,这个参数在调用时不指定,那默认就是CN,指定了的话,就用你指定的值。另外,你可能注意到了,在把country变成默认参数后,我同时把它的位置移到了最后面,为什么呢?这是语法强制的,默认参数放在其他参数后边,为啥呢? 假设允许这样:
那调⽤时
你告诉我,第3个参数python到底应该给到country还是course呢?无论给哪个,都会出现歧义,所以Python语法干脆就让你把默认参数放最后,解释器在处理函数时参数时,按优先级,位置参数>默认参数
注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值。
不定长参数(非固定参数)
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
包裹位置参数
*args
def stu_register(name,age,*args): # *args 会把多传入的参数变成一个元组形式 print(name,age,args) stu_register("Alex",22) #输出 #Alex 22 () #后⾯面这个()就是args,只是因为没传值,所以为空 stu_register("Jack",32,"CN","Python") #输出 # Jack 32 ('CN', 'Python')
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
包裹关键字参数
**kwargs
def stu register(name,age,*args,**kwargs): #*kwargs会把多传入的参数变成一个dict形式 print (name,age,args,kwargs) stu register("Alex",22) #输出 #A1ex22(){}#后面这个{}就是kwargs,只是因为没传值,所以为空 stu register("Jack",32,"CN","Python",sex="Male",province="ShanDong") #输出 Jack 32 ('CN','Python'){'province':'ShanDong','sex':'Male'}
函数的说明文档
思考:如果代码多,我们是不是需要在很多代码中找到这个函数定义的位置才能看到注释?如果想更方便的查看函数的作用怎么办?答:函数的说明文档
定义函数的说明文档 def函数名(参数): 说明文档的位置 代码 查看函数的说明文档 help(函数名)
定义函数后的第一行加函数说明文档
函数嵌套调用
所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数。
变量作用域
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。
局部变量---所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。
所谓全局变量,指的是在函数体内、外都能生效的变量。
局部变量与全局变量
看如下代码
输出
为什么在函数内部改了name的值后,在外面print的时候却没有改呢?因为这两个name根本不是一回事
在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域(即有效范围)是整个程序,局部变量作用域是定义该变量的函数。
变量的查找顺序是局部变量>全局变量
当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。
在函数里是不能直接修改全局变量的
就是想在函数⾥修改全局变量怎么办?
global name 的作用就是要在函数⾥声明全局变量name ,意味着最上⾯的name = “Alex Li” 即使不写,程序最后面的print也可以打印name,虽然可以改,但不建议⽤这个global语法,随着代码增多 ,会造成代码调试困难
传递列表、字典产⽣的现象
执⾏结果 {‘name’: ‘Alex’, ‘age’: 26, ‘hobbie’: ‘学习’} [‘Rebeeca’, ‘Katrina’, ‘Rachel’, ‘XiaoYun’] 不是说不能在函数⾥里改全局变量么,怎么改了呀?
根据上图我们能看出,程序只是把d这个dict的内存地址传给了change-data函数,把dict比作鱼缸,里面的k,v比作缸里装的鱼。现在只是把鱼缸丢给了函数,这个鱼缸本身你不能改,但是里面的鱼可以。相当于只是传了一个对这个d的引用关系给到函数的形参。这样是为了减少内存的浪费,因为如果这个dict比较大,传一次到函数里就要copy一份新的值的话,效率太低了。
拆包和交换变量值
拆包
拆包:元组
def return_num(): return 100,200 num1,num2 return_num() print(num1) #100 print(num2) #200
拆包:字典
dict1 {'name':'TOM','age':18} a,b dict1 #对字典进行拆包,取出来的是字典的key print(a)#name print(b)#age print(dicti[a])#TOM print(dict1[b])#18
交换变量值
需求:有变量a = 10和b= 20,交换两个变量的值。
方法一:借助第三变量存储数据。
#1.定义中间变量 c=0 #2.将a的数据存储到c c =a #3.将b的数据20赋值到a,此时a=20 a =b #4.将之前c的数据10赋值到b,此时b=10 b =c print(a)#20 print(b)#10
方法二
引用
了解引用
在python中,值是靠引用来传递来的。我们可以用id()来判断两个变量是否为同一个值的引用。我们可以将id值理解为那块内存的地址标识。
#1.int类型 a=1 b=a print(b)#1 print(id(a)) #140708464157520 print(id(b)) #14070846415752© a=2 print(b) #1,说明int类型为不可变类型
print(id(a))#140708464157552,此时得到是的数据2的内存地址 print(id(b))#140708464157520 #2.列表 aa=[10,20] bb aa print(id(aa)) #2325297783432 print(id(bb)) #2325297783432 aa.append(30) print(bb)#[10,20,30],列表为可变类型 print(id(aa))#2325297783432 print(id(bb))#2325297783432
引用当做实参
def test1(a): print(a) print(id(a)) a +=a print(a) print(id(a)) #int:计算前后id值不同 b=100 test1(b) #列表:计算前后id值相同 c=[11, 22] test1(c)
可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.
可变类型
列表
字典
集合
不可变类型
整型
浮点型
字符串
元组
递归
递归是一种编程思想,应用场景:
1. 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;
2.在后续的算法课程中,很多算法都离不开递归,例如:快速排序。
2.1.1 递归的特点
函数内部自己调用自己
必须有出口
需求:3以内数字累加和
#3+2+1 def sum_numbers(num): #1.如果是1,直接返回1--出口 if num =1: return 1 #2.如果不是1,重复执行累加并返回结果 return num sum_numbers(num-1) sum_result sum_numbers(3) #输出结果为6 print(sum_result)
对真实数据进行一次次的传递,到出口后返回值返回前一次函数的调用回到第一次调用
lambda表达式(匿名函数)
lambda的应用场景:
如果一个函数有一个返回值,并且只有一句代码,可以使用lambda简化。
简化代码,节省内存
lambda语法
lambda 参数列表 : 表达式
注意
lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
lambda表达式能接收任何数量的参数但只能返回一个表达式的值。
#函数 def fn1(): return 200 print(fn1) print(fn1()) #.lambda表达式 fn2 lambda:100 print(fn2) print(fn2())
注意:直接打印lambda表达式,输出的是此lambda的内存地址
需求:计算a + b
函数实现
def add(a,b): return a +b result add(1,2) print(result)
lambda实现
fn1 lambda a,b:a +b print(fn1(1,2))
lambda的参数形式
无参数
fn1 lambda:100 print(fn1())
一个参数
fn1 lambda a:a print(fn1('hello world'))
默认参数
fn1=lambda a,b,c=100:a b +c print(fn1(10,20))
可变参数
不定长位置参数*args
fn1 lambda *args:args print(fn1(16,20,30))
不定长关键字参数**kwarge
fn1 lambda **kwargs:kwargs print(fn1(name='python',age=20))
lambda的应用
带判断的lambda
fn1 lambda a,b:a if a >b else b(三目运算) print(fn1(1000,500))
列表数据按字典key的值排序
students {'name':'TOM','age':20}, {'name':'ROSE','age':19}, {'name':'Jack','age':22) ]
#按name值升序排列 students.sort(key=lambda x:x['name']) print(students) #按name值降序排列 students.sort(key=lambda x:x['name'],reverse=True) print(students)
sort() 是 Python 中用于对列表进行排序的函数,它可以按照升序或降序排列元素。 以下是 sort() 函数的语法规则: list.sort(key=None, reverse=False) 其中: key:可选参数,用于排序的关键字。默认为 None,表示按照列表中元素的原始顺序排序。如果指定了 key,则会按照指定的关键字进行排序。例如,list.sort(key=len) 表示按照列表中元素的长度进行排序。 reverse:可选参数,表示是否按照降序排列。默认为 False,表示按照升序排列。如果指定为 True,则会按照降序排列。例如,list.sort(reverse=True) 表示按照降序排列。
高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
目的:化简代码
需求:任意两个数字,按照指定要求整理数字后再进行求和计算。
def sum_num(a,b,f): return f(a)+f(b) result sum_num(-1,2,abs) print(result) #3
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
内置高阶函数
map()
map(func, Ist),将传入的函数变量func作用到Ist变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
需求:计算 list1 序列中各个数字的2次方。
1ist1=[1,2,3,4,5] def func(x): return x *2 result map(func,list1) print(result)<map object at 0x0000013769653198> print(1ist(resu1t))#[1,4,9,16,25]
reduce()
reduce(func,Ist),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。
注意:reduce()传入的参数func必须接收2个参数。
需求:计算 list1 序列中各个数字的累加和。
import functools 1ist1=[1,2,3,4,5] def func(a,b): return a b result functools.reduce(func,list1) print(result) #15
filter()
filter(func, Ist)函数用于过滤序列,过滤掉不符合条件的元素,返回一个filter对象。如果要转换为列表,,可以使用 list()来转换。
1ist1=[1,2,3,4,5,6,7,8,9,10] def func(x): return x 2 =0 result filter(func,list1) print(result)<filter object at 0x0000017AF9DC3198> print(list(result))#[2,4,6,8,10]
1.6 内置函数
Python的len 为什么你可以直接⽤?肯定是解释器器启动时就定义好了
画红线的是咱们这个集训营必须要学的,其它的有兴趣可以⾃自⼰己探索。内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii
每个函数的作⽤用我都帮你标好了 1. abs # 求绝对值 2. all #Return True if bool(x) is True for all values x in the iterable.If the iterable is empty, return True. 3. any #Return True if bool(x) is True for any x in the iterable.If the iterable is empty, return False. 4. ascii #Return an ASCII-only representation of an object,ascii(“中国”) 返回”‘\u4e2d\u56fd’” 5. bin #返回整数的2进制格式 6. bool # 判断⼀一个数据结构是True or False, bool({}) 返回就是False, 因为是空dict 7. bytearray # 把byte变成 bytearray, 可修改的数组 8. bytes # bytes(“中国”,”gbk”) 9. callable # 判断⼀一个对象是否可调⽤用 10. chr # 返回⼀一个数字对应的ascii字符 , ⽐比如chr(90)返回ascii里的’Z’ 11. classmethod #⾯面向对象时用,现在忽略 12. compile #py解释器⾃⼰⽤的东西,忽略 13. complex #求复数,⼀般⼈人⽤不到 14. copyright #没⽤ 15. credits #没⽤ 16. delattr #面向对象时⽤用,现在忽略 17. dict #⽣成⼀一个空dict 18. dir #返回对象的可调⽤属性
19. divmod #返回除法的商和余数 ,⽐比如divmod(4,2),结果(2, 0) 20. enumerate(可遍历对象,start = 0) #返回列表的索引和元素,比如 d = [“alex”,”jack”],enumerate(d)后,得到(0, ‘alex’)(1, ‘jack’) 21. eval #可以把字符串串形式的list,dict,set,tuple,再转换成其原有的数据类型。 22. exec #把字符串串格式的代码,进行解义并执⾏,⽐比如exec(“print(‘hellworld’)”),会解义⾥面的字符 串并执⾏ 23. exit #退出程序 24. filter #对list、dict、set、tuple等可迭代对象进⾏行行过滤, filter(lambda x:x>10, [0,1,23,3,4,4,5,6,67,7])过滤出所有⼤大于10的值 25. float #转成浮点 26. format #没⽤用 27. frozenset #把⼀一个集合变成不可修改的 28. getattr #⾯面向对象时⽤用,现在忽略 29. globals #打印全局作⽤用域⾥的值 30. hasattr #⾯面向对象时⽤用,现在忽略 31. hash #hash函数 32. help 33. hex #返回⼀一个10进制的16进制表示形式,hex(10) 返回’0xa’ 34. id #查看对象内存地址 35. input 36. int 37. isinstance #判断⼀一个数据结构的类型,⽐比如判断a是不不是fronzenset, isinstance(a,frozenset) 返 回 True or False 38. issubclass #面向对象时⽤用,现在忽略 39. iter #把⼀一个数据结构变成迭代器器,讲了迭代器器就明白了 40. len() 计算容器中元素个数 41. list() 将某个序列转换成列表
42. locals 43. map # map(lambda x:x**2,[1,2,3,43,45,5,6,]) 输出 [1, 4, 9, 1849, 2025, 25, 36] 44. max # 求最大值 45. memoryview # ⼀一般⼈人不用,忽 46. min # 求最小值 47. next # ⽣生成器器会⽤用到,现在忽略 48. object #⾯面向对象时⽤用,现在忽略 49. oct # 返回10进制数的8进制表示 50. open 51. ord # 返回ascii的字符对应的10进制数 ord(‘a’) 返回97, 52. print 53. property #⾯面向对象时⽤用,现在忽略 54. quit 55. range(start,end,step) 生成从start到end的数字,步长为step,供for循环使用 56. repr #没什什么⽤用 57. reversed # 可以把⼀一个列列表反转 58. round #可以把小数4舍5⼊成整数 59. set() 将某个序列转换成集合 60. setattr #⾯面向对象时⽤用,现在忽略 61. slice # 没⽤用 62. sorted 63. staticmethod #面向对象时用,现在忽略 64. str 65. sum #求和,a=[1, 4, 9, 1849, 2025, 25, 36],sum(a) 得3949 66. super #⾯面向对象时⽤用,现在忽略 67. tuple(), 将某个序列转换成元组 68. type 69. vars #返回⼀一个对象的属性,⾯面向对象时就明⽩白了了 70. zip #可以把2个或多个列列表拼成⼀一个, a=[1, 4, 9, 1849, 2025, 25, 36],b = [“a”,”b”,”c”,”d”], list(zip(a,b)) #得结果 [(1, 'a'), (4, 'b'), (9, 'c'), (1849, 'd')]
1.7 练习题:学籍注册程序
需求:
1. 要求用户输⼊姓名、年龄、⼿手机号、身份证号、所选课程,然后为学员完成注册
2. 手机号、身份证号唯一
3. 可选的课程只能从Python、Linux、网络安全、前端、数据分析 这⼏⻔⾥选
4. 学员信息存入⽂文件
1.8 练习题:炸⾦花棋牌游戏
需求:
1. 允许用户⼀次性输⼊多个玩家姓名,不限个数,然后为每个玩家随机⽣成3张牌
2. 你只有⼀一付扑克牌,确保发出去的每张牌不不重样
3. 牌需要有⿊桃、红桃、⽅⽚、梅花之分
三、实战: 给员⼯⾃自动批量发工资条
处理以下excel表, 批量给每个员工发工资条
格式如下:
四、实战:批量从1000号员⼯word简历中调取技能关键词
五、作业:生成1000张学员海报
需求:
1. 1000张海海报名字不同, 改在图片LTing处
2. 为每为同学的海报⽣生成单独的2维码(选做)
一、Web开发介绍
我们看到的网页通过代码来实现的,这些代码由浏览器解释并渲染成你看到的丰富多彩的页面效果。这个浏览器就相当于Python的解释器,专门负责解释和执行(渲染)网页代码。
写网页的代码是专门的语言,主要分为Hmtl \CSS \ JavaScript,被称为网页开发三剑客,分别作用如下
Html
超文本标记语言(英语: HyperText Markup Language,简称: HTML)是一种用于创建网页的标准标记语言。主要负责编写页面架构,有点像建房子时,造的毛坯房。
CSS
CSS (Cascading Style Sheets)用于渲染HTML元素标签的样式。让你的网页样式变的丰富多彩起来,可以改变字体、颜色、排列方式、背景颜色等相当于给你的毛坯房做装修
JavaScript
周杰伦= 周杰网页脚本语言,可以让你的网页动起来,比如一张图片鼠标放上去自动变大、一个按钮自动变色、提交表单时少填或填错了字段会提示报错等,都是JavaScript实现的。
⼆、HTML
2.1 HTML简介
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>路飞学城</title> </head> <body> <h1>我的第⼀个标题</h1> <p>我的第⼀个段落。</p> </body> </html>
<!DOCTYPE html> 声明为 HTML5 ⽂文档 <html> 元素是 HTML 页面的根元素 <head> 标签用于定义文档的头部,它是所有头部元素的容器 中的元素可以引用脚本、指示浏览器在哪⾥找到样式表、提供元信息等等。 <meta> 元素包含文档的元数据, 如定义网页编码格式为 utf-8、关键词啥的 <title> 元素⾥描述了文档的标题 <body> 元素包含了可见的页面内容 <h1> 元素定义⼀个⼤大标题 <p> 元素定义⼀个段落
2.2 什么是HTML?
HTML 是用来描述⽹页的⼀种语⾔。
HTML 指的是超文本标记语言: HyperText Markup Language
HTML 不是⼀种编程语言,⽽是⼀种标记语言
标记语⾔言是⼀套标记标签 (markup tag)
HTML 使用标记标签来描述⽹页
HTML 文档包含了HTML 标签及文本内容
HTML文档也叫做 web 页面
HTML 标签
HTML 标记标签通常被称为 HTML 标签 (HTML tag)。
HTML 标签是由尖括号包围的关键词,⽐如
HTML 标签通常是成对出现的,比如<b> 和 </b> ,标签对中的第一个标签是开始标签,第二个标签是结束标签
2.3 HTML⽹⻚结构
下⾯是⼀个可视化的HTML页面结构:
注意: 只有 区域 ( ⽩⾊部分) 才会在浏览器器中显示。 seo optimiaztion sem search engine marketing
三、HTML常⽤元素⼊门
3.1 HTML标题
3.2 段落
3.3 超链接
<body> <a href="https://www.luffycity.com">这是⼀一个链接使⽤用了了 href 属性</a> </body>
<a href="https://www.luffycity.com" target="_blank" >访问路飞学城</a>
target="_blank" 会打开一个新窗口
3.4 显示图片
<img src="black_girl.jpg" width="600" height="500" >
3.5 HTML表格
想在页面上显示这种表格怎么做?
先做个最简单的
输出
表格的表头
表格的表头使用标签进⾏定义。
大多数浏览器会把表头显示为粗体居中的文本
可以加上边距
<table border="1" cellpadding="10">
3.6 列表
分为有序列表和⽆序列表
有序列表
<ol> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ol> <ol start="50"> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ol>
效果
无序列表
嵌套列表
3.7 div区块元素
HTML 区块元素
大多数 HTML 元素被定义为块级元素或内联元素。
块级元素在浏览器显示时,通常会以新⾏来开始(和结束)。
HTML 内联元素
内联元素在显示时通常不会以新⾏开始。
实例:
HTML <div> 元素
HTML
元素是块级元素,它可⽤于组合其他HTML 元素的容器。
<div>
<div>元素没有特定的含义。如果与CSS 一同使用,元素可用于对大的内容块设置样式属性。
<div> 元素的另⼀一个常见的用途是文档布局。它取代了使⽤表格定义布局的⽼式⽅法。使⽤元素进行文档布局不是表格的正确用法。
<span> 元素
HTML 元素是内联元素,可⽤用作文本的容器
元素也没有特定的含义。当与 CSS ⼀一同使用时, 元素可用于为部分文本设置样式属性。
3.8 CSS样式初识
CSS (Cascading Style Sheets) 用于渲染HTML元素标签的样式。
CSS 可以通过以下方式添加到HTML中:
内联样式- 在HTML元素中使用"style"属性
内部样式表 -在HTML文档头部 区域使用