python基础学习

一.pycharm使用入门

1.creat project

  • 虚拟环境:基于系统环境copy的一个环境,python的版本是依据于系统环境的python版本

  • 系统环境:

    1. 对比于用户来说,是不受制用户登录的限制,所有的用户都可以使用

    2. 对比于虚拟环境,是相互独立的,互不干扰--比如我在系统环境中安装了一个python的依赖包,虚拟环境是不会对应安装的(不存在的,需要单独去安装)

    3. 在pycharm项目中。可以随意更换项目所依赖的环境

      • 所有的python项目都是需要依据环境来运行的--python脚本

      • 项目和python环境是可以分开的,只不过是受制于python环境中的依赖包

      • 项目的内容不要放在环境的目录下面

pycharm使用系统环境,不会去创建venv目录

pycharm创建项目之后

first:是命名的项目名称

vevn文件夹:虚拟环境的文件夹(不懂的话,千万不要乱动)

新建文件的时候,需要右键项目名称的文件夹,然后创建文件 -- 千万不要在venv目录下面创建文件

2.安装依赖包

  1. pip install 依赖包

pip install 依赖包名称 -i 镜像源地址

安装在系统环境就在系统环境,虚拟环境没有;安装在虚拟环境同理

如果需要安装历史版本,就采用以下方式:

  1. 点击右边的 Specify version 勾选框

  2. 点击右边的下拉框按钮

  3. 选择所需要的版本

  4. 点击Install Package

注意:如果网络不太好的情况下,可能出不来版本信息,那么就采用命令下载的方式

国内镜像源:

https://pypi.douban.com/simple/ 豆瓣

 https://mirrors.aliyun.com/pypi/simple/ 阿里

 https://pypi.hustunique.com/simple/ 华中理工大学

 https://pypi.sdutlinux.org/simple/ 山东理工大学

 https://pypi.mirrors.ustc.edu.cn/simple/ 中国科学技术大学

 https://pypi.tuna.tsinghua.edu.cn/simple/ 清华

查看某一个依赖包安装的信息,执行命令:pip show 依赖包的名字:

pip show pytest

怎么把项目所需要的环境,传递给同事 -- 统一依赖包的版本(python的版本也要一样)

\# 示例:导出的文件名称可以自定义 
pip freeze > request.txt

request.txt :自己定义的文件名

  1. 通过pycharm打开项目文件,然后创建一个虚拟环境

    但凡是图标带V的,都是指代的虚拟环境,反之表示系统环境

2.拿到 request.txt 文件之后,执行命令,会按照request.txt 文件的要求,去下载依赖包的相关信息:

\# 建议加上国内的镜像源 
pip install -r output.txt -i https://mirrors.aliyun.com/pypi/simple/

cmd执行方式

二.python的输入输出、数据类型

1.输入输出

 #输出 print
 print("hello world")
 """
 注释
 单引号和双引号没区别,但单引号和双引号要成对出现
 """
 '''
 注释
 多行注释:鼠标选中要注释的内容,然后 ctrl + /
 格式化代码:ctrl + alt + L (L=shift +l)
 直接复制上一行代码:ctrl + D
 '''
 #输入 input
 a=input("请输入密码")
 print(a)
 print("请输入您的密码:"+input())
 """
 程序是有开始,有结束的---绝大数情况下
 程序的运行规则:从上到下,由内而外----重点
 """
 ​

2.格式化输出

 """
 方式一:
 使用%d、%f、%s   进行占位,后面的输出内容使用 %(value1, value2, value3)
 %d : 整数
 %f:小数/浮点数
 %s:字符串
 """
 print("""
     =====自我介绍=====
     name: %s
     addr: %s
     age: %d
     sal: %f
 """ % ("七夜老师", "湖南长沙", 18, 1001))
 ​
 """
 方式二:
 直接使用 {} 进行占位,后面接 .format(value1, value2),
 前面设置了几个占位符{},后面就需要传入几个值
 """
 ​
 print("""
     =====自我介绍=====
     name: {}
     addr: {}
     age: {}
     sal: {}
 """.format("七夜老师", "湖南长沙", 18, 1001))
 ​
 """
 方式三:在字符串引号前面加个f(只适用于变量)
 然后字符串中间用{}
 把变量的名称括起来
 示例:
 """
 name, age, sex = "七夜老师", 18, "man"
 print(f"名字:{name}")
 print(f"年龄:{age}")
 print(f"性别:{sex}")
 ​
 # 打印的结果
 """
 名字:七夜老师
 年龄:18
 性别:man
 """

3.数字类型

常见的数字类型:
  1. 整数: 0-9组成的数字 int

  2. 浮点数:整数 + 小数点 + 小数 float

  3. 布尔值:对或者错 真(True)或者假(False),如果是做计算的话,True == 1,False == 0 bool

  4. 复数:实数 + 虚数,complex,比如:0.99j

type()用来获取数据的类型

示例:

 print(type(9))  # <class 'int'> 
 print(type(1 > 2))  # <class 'bool'>
 print(type(3 < 1))  # <class 'bool'>
 print(type(100 + 0.99j))  # <class 'complex'>
 ​
字符串类型
 print("True")
 print(True)

带""的都属于字符串类型

4.变量的应用

定义:在计算机中,能够指代某个值或者结果的东西 -- 变量

用一个英文单词/字母,去代替某些值的时候,可以直接把这个单词/字母拿过来使用 -- 这个单词/字母称之为变量

举例:求圆的面积公式 S=π*r²,S为变量

 num1=2 #在计算机中,=号,一个=号表示赋值,把最右边的值,赋值给左边的变量
 num2=7 #  ==号,两个便是判断是否等于的意思
 # + - * / 对于python中的加减乘除

注意:python中,定义变量的时候,可以直接赋值,不需要提前去定义类型(区别:java语言)

多个变量赋值:

连续赋值:多个变量使用同一个值

 a = b = 10
 print(a)
 print(b)
 print(id(a))#输出a b的内存地址,值一样,地址相同
 print(id(b))

多个变量使用多个值

 name, age, sex = "七夜老师", 18, "man" print(name)
 print(age)
 print(sex)

一个变量赋多个值:* 号进行接收----* 号表示解包

 a, b, *c = 1, 2, 3, 4, 5, 6, 7, 8, 9 
 print(f"a收到的值:{a}") 
 print(f"b收到的值:{b}") 
 print(f"c收到的值:{c}")

只能有一个* 号

5.类型转换

字符串--->整数 int("字符串(注意:数字类型)")

字符串--->浮点数 float()

字符串--->布尔值 boot()

字符串--->字符串 str()

示例一:

 str1 = "100" a = int(str1)
  print("str1的数据类型:",type(a))  # <class 'int'>

示例二:

 # 错误的示例 
 str2 = "3.14" 
 a = int(str2)
 print("str2的数据类型:",type(a)) 
 # 正确的写法 
 str2 = "3.14" 
 a = float(str2) 
 b = int(a) 
 print(b)
 print("str2的数据类型:",type(b))
 #浮点类型字符串不能直接转换为int类型 不进行四舍五入

课后作业

1.输入两个数字,并且同时打印出来

2.请将字符串"3.1415926"转为浮点型并且乘以2,再转为整型进行输出

3.【项目】利用上课学过的知识完成以下需求实战:(利用format完成占位输出)

# 需求:

1)打印"欢迎来到xx同学的python书店" # 2)定义变量接收(book_name:"python",book_author:"七夜",book_num:10,book_price:77) # 3)最后格式化打印: # 同学你好,你需要购买的书籍名称为: {} ,价格为: {}元, # 作者为: {} , 当前库存数量为: {} 本,祝你学习愉快!~~

 print("----欢迎来到ljl同学的python书店----")
 book_name = input("请输入书籍的名称:")
 book_author = input("请输入书籍的作者:")
 book_num = input("请输入书籍的库存数量:")
 book_price = input("请输入书籍的售卖价格:")
 print("""
     同学你好,你需要购买的书籍名称为: {} ,价格为: {}元,
     作者为: {} , 当前库存数量为: {} 本,祝你学习愉快!~~
 """.format(book_name, book_price, book_author, book_num))
 

三、python中的运算符、条件分支结构、循环结构

运算符

1.算数运算符

常见的运算符: 加(+) 减(-) 乘(*) 除( /)

  print(num1 + num2)
  print(num1 - num2)
  print(num1 * num2)
  print(num1 / num2)
  # 问:运算的结果? 坑 15 5 50 2.0

注意:在做除法运算的时候,会出现一个小数点 -- 浮点数的类型

复杂的用法:

1)求余数: %

举个例子:现在有10个文件,分给3个人,请问余数为多少? -- 1

 num1 = 10 
 num3 = 3 
 print("所得到的余数为: {}".format(num1 % num3))
 # 运算的结果 所得到的余数为: 1

2)整除(只会取整数): //

num1 = 10
num3 = 3 
print("整除后的结果为: {}".format(num1 // num3))
# 整除后的结果为: 3

3)幂(次方): **

num1 = 10 
num3 = 3 
print("次方得到的结果为: {}".format(num1 ** num3))
# 次方得到的结果为: 1000

特殊的用法:

举例:如果一半是数字,一半不是?

1)str类型 和 str类型:

两个str类型的值进行加法运算 -- 拼接(不要默认给英文单词之间,加上空格)

str1 = "hello" 
str2 = "world" 
print("两个str类型的值,进行加法计算的结果:{}".format(str1 + str2)) 
# 两个str类型的值,进行加法计算的结果:helloworld

2)str类型 和 数字类型:

多次打印str类型,打印的次数由数字类型决定

str1 = "hello" 
num4 = 3
print(str1+num4) 
#str和数字类型不能相加,可以相乘
print("str类型和数字类型,进行乘法运算:{}".format(str1 * num4))
# str类型和数字类型,进行乘法运算:hellohellohello

示例:

print("-" * 100) # ----------------------------------------------------------------------------------------------------

其他多种类型运算:

1)int类型 和 float类型:有可能存在一个问题 -- 精准度丢失(python的语言问题,不需要额外关注)

data = 3 
f2 = 2.111
print("int类型 + float类型,得到的结果:{}".format(data + f2))
# int类型 + float类型,得到的结果:5.111000000000001

2)bool类型 和 int类型:

bool类型,在做计算的时候,True == 1, False == 0

bol = True 
 # 直接定义的bool类型 data = 3
 # 非0为true
print("bool类型 + int类型,得到的结果:{}".format(bol + data))
# bool类型 + int类型,得到的结果:4
2. 比较运算符

包含:大于、小于、等于、不等于、大于等于、小于等于

返回的结果:bool值,True、False

等于: ==

不等于:!=(英文格式)

大于等于:>=

小于等于:<=

a = 10 
b = 5 
print(f"大于:{a > b}") 
print(f"小于:{a < b}") 
print(f"等于:{a == b}") 
# 两个=号,表示判断是否相等 
print(f"不等于:{a != b}") 
# != 表示不等于 
print(f"大于等于:{a >= b}") print(f"小于等于:{a <= b}")
# 结果: 大于:True 小于:False 等于:False 不等于:True 大于等于:True 小于等于:False
3.赋值运算符

单个的=号,表示赋值的意思

赋值:把=号,右边的值,赋值给左边

a = 10 
a += 5  # 属于简写:a = a + 5 的结果 
print(f"a += 5 的结果:{a}") 
# 结果:a += 5 的结果:15 
a -= 5 
a *= 5 
a /= 5

注意事项:程序的执行顺序(从上到下,由内而外)

a = 10
a += 5
a *= 5
print(f"a += 5 的结果:{a}") 
# a += 5 的结果:75
4.逻辑运算符

返回的结果:bool值,True、False

包括:与(and) 或(or) 非(not)

定义:

与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假

或运算:只要有一个逻辑是True最终结果就是True -- 同假为假,有真为真

非运算:不管别人是正确还是错,他一定要反对 -- 杠精,相对

示例:

a = True
 b = False 
 print(f"与运算:{a and b}")  
# False
print(f"或运算:{a or b}") 
# True
print(f"非运算:{not b}")
# True

练习:

1)优先级:比较 > 逻辑

print(1 > 2 and 4 > 3) 
 # False
 # False and True
 # False
print(1 > 2 or 4 > 3)  
# True 
# False or True # True

答:True and False,与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假

2)优先级:not > and > or

print(True and False or True and not False)  
# True 
# True and False or True and True
# False or True # True

3)优先级:算数 > 比较 > 逻辑(not > and > or)

print(1 + 1 > 1 + 2 and 3 + 2 < 3 - 1 or 5 and not True) 
# False # 2 > 3 and 5 < 2 or 5 and not True 
# False and False or 5 and not True 
# False and False or 5 and False
# False or False # False

提问:5 and False,这个地方的值为多少?

答:False

False or 5 输出结果为 :5

  1. 与运算:所有逻辑都是True,最终结果才是True -- 同真为真,有假为假

  2. 做判断的时候:非0则为True

5.成员运算符

定义:判断指定内容是否包含在某个内容中 包含关系

返回的结果:bool值,True、False

in:存在(包含)

not in:不存在(不包含)

示例:

str1 = "qiyelaoshi"
print("判断'qiye'是否存在str1变量里面:{}".format('qiye' in str1))  
# True 
print("判断'qiye'是否存在str1变量里面:{}".format('qiye' not in str1))
# False

注意:

1)bool类型的数据,是不能够做成员运算符的计算:

bol = True print("'T'是否存在bol变量里面:".format('T' in bol))
# 报错信息:argument of type 'bool' is not iterable

2)数字类型的数据,是不能够做成员运算符的计算:

num1 = 123
#数字是一个整体,无法去判断包含还是不包含
print(1 in num1)
# 报错信息:argument of type 'int' is not iterable

条件分支结构

1.单向分支

语法结构:

if 判断条件(运算符、bool值):    
    逻辑代码(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行)    

示例:如果用户输入了'admin'的内容,那么输出'欢迎管理员登录'

name = input("提示用语[请输入您的登录账号]: ") 
# 用变量接收输入的值 
if name == 'admin':  
    # 判断的条件:拿[输入的内容]和[预期结果]作是否相等的判断   
    print("欢迎管理员登录")

2.双向分支

如果条件不满足,那么就执行另一块代码,这两块代码一定不会同时执行

语法结构:

if 判断条件(运算符、bool值): 
    逻辑代码(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) 
else:  
    逻辑代码(if条件不满足的情况下,才会执行else,如果满足if条件,则跳过else代码块,不执行)

示例:排除特殊性的场景,如果你不是一个男孩子,那么一定是一个女孩子

sex = input("请问您是男孩子么?请输入:yes 或 no:") 
if sex == 'yes':   
    print("那你应该喜欢打篮球")
else:  
    print("那你应该喜欢口红")

3.多向分支

存在多个条件判断,只要满足一个条件,就不会去执行其他条件

语法结构:

if 判断条件1(运算符、bool值):  
   #逻辑代码1(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行)
elif 判断条件2:  
    #逻辑代码2(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行)
elif 判断条件3:  
    #逻辑代码3(1. 如果条件满足 -- True,就执行这部分逻辑代码; 2. 如果不满足,就跳过这段逻辑代码,不执行) ... ... 
else:   
    #逻辑代码(如果以上条件都不满足,才会执行else,如果满足以上的任意条件,则跳过else代码块,不执行)

示例:买票的条件

\1. 60以上,3以下 [免票]

\2. 12 - 59 成人票[全票]

\3. 4 - 11 儿童票[半票]

age = int(input("请输入您的年龄:"))
# int(需要转换的数据)
if age >= 60 or age <= 3:
    # [免票]的区间   
    print("[免票]") 
elif age >= 12 and age < 60: 
    # 成人票[全票]的区间   
    print("成人票[全票]") 
elif age >= 4 and age < 12:  
    # 儿童票[半票]  
    print("儿童票[半票]")

注意:input()方法接收的值,都是str类型

4.if判断条件

理论上说 if 后面可以接任意条件,只要它的结果是bool值就行

使用的情况:

  • 比较: > < ==

  • 逻辑: and or not

  • 成员:in not in

  • 数学: + - * /

  • 直接使用bool值

示例:

\# 1)
if 1 - 1:  
    # 1 - 1 = 0,非0则为True,0则为False 
    print("if打印的内容")
else:    
    print("else打印的内容")     
# 2) 
b = input("请输入文字:")
if 'qiye' in b:    
    print("if打印的内容") 
else:   
    print("else打印的内容")    
# 3) 
a = int(input("请输入数字:"))
if a - 1:  
    # 1 - 1 = 0   
    print("if打印的内容") 
else:  
    print("else打印的内容")

5.子分支

if的嵌套,if ... else ...里面再去嵌套 if ... else ...

if 条件1:
    代码块1
    
    if 条件2:
        代码块2
    else:
        代码块b
 else:
    代码块b
 
   #if和else可以无限嵌套     

示例:相亲的条件,条件1:满足180身高;条件2:满足月薪100;

hight = int(input("请输入相亲对象的身高:")) 
if hight >= 180:  
    print("可以考虑一下")    
    sal = int(input("请输入相亲对象的工资:"))    
    if sal >= 100:    
        print("可以见一面")  
    else:       
        print("我还是考虑考虑吧") 
    else:   
        print("不好意思,不考虑,我要加班")

循环结构_while

1.while循环

让某段代码逻辑去反复执行,这个就叫循环,具体的执行次数,就是由条件决定的

语法结构:

while 判断条件:
    逻辑代码

  1. 只要判断条件为True这个代码块就会反复执行,执行到代码的最后一行重新判断条件,

  2. 如果判断条件还是True就继续执行一次,如此反复

  3. 如果判断条件是False,就跳出循环

  4. while是关键字(python固定设置的内容)

  5. 如果while的判断条件,始终满足----一直执行/死循环-----避免---改变while的条件

示例:

while True:
    print("欢迎来到七夜老师的课堂!")

注意:当while的判断条件始终为True的时候,会进入死循环

不要让while的循环条件恒定,需要有办法改变它原来的条件

方式一:引用变量,让条件不会恒定,让变量可以变化,同时与while条件相结合

a = 0  # 设置一个初始值 
while a < 6: 
    # a的取值:0、1、2、3、4、5 
    print("欢迎来到七夜老师的课堂!")  
    a += 1
    # a每循环一次,就会在原有的基础上进行 +1    
    # 提问:会打印几次?6次
2.关键字避免死循环

break :直接终止整个循环,不去判断条件,直接结束循环

continue:遇到continue这个关键字,这个时候不去执行循环内部往下的代码(循环内部),直接重新去判断条件

区别:

continue:中断当前循环,直接执行判断条件。如果条件为True,继续执行,如果条件为False,就停止循环

break:直接中断整个循环,不去判断条件,直接循环结束

示例:

a = 10  # 设置的初始值
while a:
    # a的取值为:9、8、7、6、5、4  
    a -= 1   
    if a % 2 == 0:        
        print(f"当前的值为偶数,此时a的值为:{a}")      
        continue  # 中断当前循环,直接执行判断条件    
        if a < 5:      
            print(f"当a的值小于5了,直接结束循环,此时a的值为:{a}")    
            break  
            # 中断整个循环,直接结束
            # 提问:当a的值为多少的时候,跳出循环?3 
            # 同学们的问题:为什么不是4的时候,跳出循环?
            # 程序的运行顺序,从上往下,a=4时会先满足第一个if判断的时候,直接continue,重新判断条件,然后重新回到a-=1去执行,然后a=3,不满足第一个if条件不执行,就到了第二个if中执行,然后就遇到了break终止循环
            

课后作业

"""
1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果
(涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)

2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串,并通过if判断对两个数字进行运算和结果输出
(涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)

3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作",输入"exit"退出系统功能(while、continue、break)

4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给20%的折扣,
编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格

5.输入一个年份,输出是否为闰年。
闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年

6.完成一个猜数字游戏

# 进入程序后

# 提示用户输入 要猜的数字

# 其他人输入时,提示数字大了,或者小了

# 猜到正确的"""
1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果
(涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)

2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串,并通过if判断对两个数字进行运算和结果输出
(涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)

3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作",输入"exit"退出系统功能(while、continue、break)

4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给200%的折扣,
编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格

5.输入一个年份,输出是否为闰年。
闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年

6.完成一个猜数字游戏
# 进入程序后
# 提示用户输入 要猜的数字
# 其他人输入时,提示数字大了,或者小了
# 猜到正确的数字为止,提示恭喜猜对了
# (选做:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始)
# (选做: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数)

# 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级
#     模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点)
"""
# 1.定义两个变量num_1、num_2接收两个浮点型的数字字符串,然后进行转换,并且分别打印出加减乘除的计算结果
# (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)
# num_1 = float(input("请输入第一个数字:"))
# num_2 = float(input("请输入第二个数字:"))
# print("加法计算的结果为: {}".format(num_1 + num_2))
# print("减法计算的结果为: {}".format(num_1 - num_2))
# print("乘法计算的结果为: {}".format(num_1 * num_2))
# # print("除法计算的结果为: {}".format(num_1 / num_2))
# print("除法计算的结果为: {}".format(round((num_1 / num_2), 2)))

# 2.定义两个变量num_1、num_2接收两个浮点型的数字字符串,进行类型转换,然后再定义一个变量operation_symbol接收一个加减乘除的字符串,
# 并通过if判断对两个数字进行运算和结果输出
# (涉及到精准度问题,需要保留小数点后两位小数,使用round(x,2)方法,x为值,2为小数点后两位)
# num_1 = float(input("请输入第一个数字:"))
# num_2 = float(input("请输入第二个数字:"))
# operation_symbol = input("请输入(+、-、*、/)中的运算符号:")
#
# if operation_symbol == "+":
#     print(num_1 + num_2)
# elif operation_symbol == "-":
#     print(num_1 - num_2)
# elif operation_symbol == "*":
#     print(num_1 * num_2)
# elif operation_symbol == "/":
#     print(round((num_1 / num_2), 2))

# 3.结合以上条件,引用while循环,让其可以循环输入运算符号和计算结果,添加输入错误提示:"输入有误,无法识别,请重新操作",
# 输入"exit"退出系统功能(while、continue、break)
# num_1 = float(input("请输入第一个数字:"))
# num_2 = float(input("请输入第二个数字:"))
#
# while True:
#     operation_symbol = input("请输入(+、-、*、/)中的运算符号:")
#     if operation_symbol == "+":
#         print(num_1 + num_2)
#     elif operation_symbol == "-":
#         print(num_1 - num_2)
#     elif operation_symbol == "*":
#         print(num_1 * num_2)
#     elif operation_symbol == "/":
#         print(round((num_1 / num_2), 2))
#     elif operation_symbol == "exit":
#         print("退出系统")
#         break
#     else:
#         print("输入有误,无法识别,请重新操作")
#         continue

# 4.一家商场在降价促销,如果购买金额50-100元(包含50和100元)之间,会给10%的折扣,如果购买金额大于100元会给20%的折扣,
# 编写一个程序,询问购买价格,再显示出折扣,(10%或20%,可以直接乘以0.1或者0.2)和最终价格
# amount = float(input("请输入购买的金额: "))
# if 50 <= amount <= 100:
#     print("您当前购买的金额享受10%的折扣,折算完的金额为: {}元".format(amount - amount * 0.1))
# elif amount > 100:
#     print("您当前购买的金额享受20%的折扣,折算完的金额为: {}元".format(amount - amount * 0.2))

# 5.输入一个年份,输出是否为闰年。
# 闰年条件:能被4整除但不能被100整除,或者能被400整除但年份都是闰年
# year_num = int(input("请输入年份:"))
# if year_num % 4 == 0 and year_num % 100 != 0 or year_num % 400 == 0:
#     print("您输入的年份是闰年!")
# else:
#     print("您输入的年份不是闰年!")

# 6.完成一个猜数字游戏
# 进入程序后
# 提示用户输入 要猜的数字
# 其他人输入时,提示数字大了,或者小了
# 猜到正确的数字为止,提示恭喜猜对了
# (选做1:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始)
# (选做2: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数)
# be_guess_num = float(input("请输入要猜的数字为: "))
#
# while True:
#     guess_num = float(input("请输入猜测的数字为: "))
#     if guess_num > be_guess_num:
#         print("数字太大!")
#     elif guess_num < be_guess_num:
#         print("数字太小!")
#     else:
#         print("恭喜你,猜对了!")
#         break

# (选做1:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始)
# be_guess_num = float(input("请输入要猜的数字为: "))
# num = 0
#
# while num < 4:
#     num += 1
#     guess_num = float(input("请输入猜测的数字为: "))
#     if guess_num > be_guess_num:
#         print("数字太大!")
#     elif guess_num < be_guess_num:
#         print("数字太小!")
#     else:
#         print("恭喜你,猜对了!")
#         break
#
#     if num == 3:
#         print("次数已用尽,正确的数字为: {},游戏重新开始".format(be_guess_num))
#         num = 0
#         continue

# (选做2: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数)
# import random
#
# be_guess_num = random.randint(1, 100)
# num = 0
#
# while num < 4:
#     num += 1
#     guess_num = float(input("请输入猜测的数字为: "))
#     if guess_num > be_guess_num:
#         print("数字太大!")
#     elif guess_num < be_guess_num:
#         print("数字太小!")
#     else:
#         print("恭喜你,猜对了!")
#         break
#
#     if num == 3:
#         print("次数已用尽,正确的数字为: {},游戏重新开始".format(be_guess_num))
#         num = 0
#         continue

# 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级
#     模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点)
print("欢迎来到七夜老师的python书店")
book_name = None
book_author = None
book_num = None
book_price = None
print(book_price, book_author, book_num, book_name)
while True:
    input_txt = input("请输入您要选择的操作\n1 - 录入书籍\n2 - 查询书籍\n3 - 退出")
    if input_txt == "1":
        book_name = input("请输入书籍的名称:")
        book_author = input("请输入书籍的作者:")
        book_num = input("请输入书籍的库存数量:")
        book_price = input("请输入书籍的售卖价格:")
    elif input_txt == "2":
        print("书籍的名称: {}".format(book_name))
        print("书籍的作者: {}".format(book_author))
        print("书籍的库存数量: {}".format(book_num))
        print("书籍的售卖价格: {}".format(book_price))
    elif input_txt == "exit":
        print("退出系统!")
        break

数字为止,提示恭喜猜对了

# (选做:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始)

# (选做: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数)

# 7.【项目】结合今天所学的内容,对上节课的作业项目进行升级

#     模拟课堂上的project_duck,改编自己的书籍项目(包含while、break、if等知识点)

"""

四、列表和字典的定义与操作

Python可视化网址:Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java

Project_Duck(烤鸭店例子):

需求:

烤鸭店利润计算器:计算这个烤鸭店每天的利润是多少?

要求:

a)要求提示页面友好

b)要求自己可以手动输入收入、成本、鸭子数量

(1)收入 - 成本 = 利润

# 第一个版本: print("欢迎使用烤鸭店利润计算器!")
price1 = input("请输入今天的收入金额为: ") 
# 1000 
price2 = input("请输入今天的成本金额为: ") 
# 600 
result = price1 - price2 
# 问题:这种方式可行么?不行,input函数所接受的值是str类型
# 报错信息:unsupported operand type(s) for -: 'str' and 'str'

优化后的代码:

# 优化后的代码:
print("欢迎使用烤鸭店利润计算器!") 
price1 = int(input("请输入今天的收入金额为: "))  
# 1000 
price2 = int(input("请输入今天的成本金额为: "))  
# 600 
result = price1 - price2 
print(f"今天的纯收入是:{result}")

(2)(单个鸭子的售卖价格 - 成本价格) * 今天售卖的鸭子数量 = 今天烤鸭店的利润

print("欢迎使用烤鸭店利润计算器!") 
price1 = int(input("请输入今天的收入金额为: "))  
# 1000 
price2 = int(input("请输入今天的成本金额为: ")) 
# 600 
duck_num = int(input("请输入今天售卖的鸭子数量为: ")) 
result = (price1 - price2) * duck_num
print(f"今天的收入金额为: {price1}, 成本金额为: {price2}, 纯收入是:{result}")

(3)由于烤鸭店的利润太少了,想要新增一些商品类型[属性:商品的名称、价格、生产日期、生产地、保质期 ... ...]

错误示例:

p1 = "北京烤鸭"
m1 = 80 
p2 = "北京卷饼"
m2 = 5 
# ... ... 要新增很多的商品,那么这种写法可行么?一种商品可能存在5条属性,那么如果有100种商品,是不是存在100 * 5 = 500行代码?
# 原因:维护性特别差,一般不这么做 -- 开发一时爽,维护火葬场

1.列表

列表的定义:

定义:一种将多个数据组合在一起的容器

标识符:[ ]

关键字:list

定义一个空列表

lst1 = []

定义一个有值的列表,每个元素之间用英文的逗号隔开

lst2 = [1, 2, 3, 4]

获取列表的类型:

lst2 = [1, 2, 3, 4] 
# 定义一个有值的列表,每个元素之间用英文的逗号隔开 
print(type(lst2))
# <class 'list'>
列表的增删改查操作:

特征:有序、可变

有序:列表中的每个元素都是有索引(python中的索引,都是默认从 0 开始)

列表的取值语法:列表的变量名称[索引的值]

lst1 = [1, 2, 3, 4, 5] 
print(lst1[3])  # 4

获取列表的长度 -- len()

lst1 = [1, 2, 3, 4, 5] 
# 有几个元素,那么len长度就是多少 
print(len(lst1))

列表可以倒叙输出 -- reverse()

lst1.reverse()  
# 先执行方法完成倒叙
print(lst1) 
# 然后再去查询

#错误写法
print(lst1.reverse())
#一边打印,一边倒叙的话,会打印为None(表示的是这个函数没有返回值)这个None在后面的函数会讲

小测验:

lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4]]

# 问题1:获取 "qiyelaoshi" 这个值

print(lst3[3])

# 问题2:请问lst3的len长度为多少?

print(len(lst3))

# 问题3:获取 3 这个值?

print(lst3[4])  
# 这个元素还是list类型的值 
#想要获取到嵌套的数据,先找到最外面的一层
print(lst3[4][2]) 
# 把lst3[4]视为一个整体的list,然后使用list取值的方式进行操作

# 问题4:lst3的长度为?

lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4], [1, 2, 3, 4, [1, 2, 3, 4], [1, 2, 3, 4]]] # 快捷的查看方式:数括号,括号是一一对应的,从最外层开始数 
print(len(lst3))
#6

列表的增加 -- append()

会把添加的值,默认加在末尾一次只能添加一个元素

lst1 = [1, 2] lst1.append("qiyelaoshi") 
print(lst1) 
# 错误示例: 
lst1.append("qiyelaoshi", "xiaominglaoshi") 
# list.append() takes exactly one argument (2 given)
列表的添加 -- insert()

通过索引来进行添加,添加的位置就是索引的位置,原有位置元素下标会依次加一?

lst1 = [1, 2] 
#按照下标完成添加,插入数据前面的下标不管,后面的数据下标依次递增+1
lst1.insert(0, "qiyelaoshi") 
print(lst1)
合并列表 -- extend()

把元素一个个的放入到新的列表中

lst1 = [1, 2] 
lst2 = [2, 3, 4, 5]
# print(lst1 + lst2)  
# 不建议在企业中,写法太低级,看起来像是加法运算 
lst1.extend(lst2) 
print(lst1)
# 把str类型的数据,合并到列表中
lst1.extend("七夜老师")
# str类型也是可以视为列表
print(lst1)  
# [1, 2, '七', '夜', '老', '师']
#错误示例,数字类型不可迭代
lst1.extend(100)
print(lst1)
列表的删除 -- remove()

直接删除具体的值,如果存在多个的话,默认删除最前的那个

lst1 = [1, 2]
lst2 = [2, 3, 4, 5, 2] 
lst1.remove(2)
print(lst1) 
# 问题:通过remove删除lst2中的值2 ,那么会删除前面的还是后面的 
lst2.remove(2) print(lst2)
列表的删除 -- pop()

不带下标,默认删除最后一个,带下标删除具体的值

lst1 = [1, 2] 
lst2 = [2, 3, 4, 5, 2] 
# lst1.pop()
# print(lst1) 
lst2.pop(3) 
print(lst2)
列表的删除--del
请删除列表中的第2至第4个元素
 del li[1:4]
列表的修改

-- 列表的变量名称[下标] = 新值

lst3 = [100, 3.14, True, "qiyelaoshi", [1, 2, 3, 4]] # 问题1:把 True 改为False?
# lst3[2] = False
# print(lst3) 
# [100, 3.14, False, 'qiyelaoshi', [1, 2, 3, 4]] 
# 问题2:把 3 改为 10 ? 
lst3[4][2] = 10 
print(lst3) 
# [100, 3.14, True, 'qiyelaoshi', [1, 2, 10, 4]]

烤鸭店项目的升级:

project_duck_3.0

print("欢迎使用烤鸭店利润计算器!") price1 = int(input("请输入今天的收入金额为: "))  # 1000 price2 = int(input("请输入今天的成本金额为: "))  # 600 duck_num = int(input("请输入今天售卖的鸭子数量为: ")) result = (price1 - price2) * duck_num print(f"今天的收入金额为: {price1}, 成本金额为: {price2}, 纯收入是:{result}")

通过列表对烤鸭店进行升级,提高代码的可维护性

project_duck_3.1

print("欢迎使用七夜老师的烤鸭店利润计算器!")
projects = {}  #定义一个最外层的的数据,用于保存
while True:  # 让系统可以循环使用,不用每次都手动执行
    # 提供一个可选择功能的菜单
    #转义字符,键盘上有部分的键,不能在代码中显示
    #\n表示换行的意思
    #如果说不希望字符串自动转义---在引号的前面加一个r,比如r"请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n"
    oper_type = input("请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n")

    if oper_type == "1":
        # 1.录入商品的功能
        pro_list = []  # 定义一个空列表

        load_name = input("请输入你的商品名:")
        pro_list.append(load_name)

        price = input("请输入你的成本价:")
        pro_list.append(price)

        s_value = input("请输入你的产地:")
        pro_list.append(s_value)

        data_time = input("请输入你的生产日期:")
        pro_list.append(data_time)

        # 问题:怎么把pro_list的值,加到projects里面去?
        projects[load_name]=pro_list

    elif oper_type == "2":
        # 2.查询商品的功能
        print(projects)
        po_name=input("请输入你要查询的商品名称:")
        print(f"您要查询的商品信息:{projects[po_name]}")

    elif oper_type == "3":
        # 3.退出系统的功能
        break  # 直接跳出整个循环

    else:
        print("系统无法识别你的输入,请重新选择!")
        continue  # 跳出当前循环,重新判断条件

2. 字典

字典的定义:

定义:具有键值对映射关系的一组无序的数据组合

键值对映射: key : value -- key是键名,value是这个键所对应的具体值,通过key来查询

关键字:dict

标识符:{}

无序:没有索引 一个字典里的key不会重复

key:是唯一的,并且不能修改的数据,通常我们用str类型

value: 可以是任何类型的数据,可以修改

定义一个空字典

dic1 = {}

定义一个有值的字典

dic2 = {   
    "name": "七夜老师",  
    "age": 18,   
    "cls": 234, 
    "students_name": ["二师兄", "千寻", "听风、", "自由"] }

字典的查询 -- 字典的变量名称["key"]`

dic2 = {   
    "name": "七夜老师", 
    "age": 18,  
    "cls": 234,  
    "students_name": ["二师兄", "千寻", "听风、", "自由"] }
print(dic2["students_name"])  # ['二师兄', '千寻', '听风、', '自由']

小测验:

问题:查询 听风、这个值?

dic2 = {   
    "name": "七夜老师",   
    "age": 18,    
    "cls": 234,   
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
print(dic2["students_name"][2])  # 听风、
字典的增删改操作:
字典的新增

字典的变量名称["字典中不存在的key"] = 新值---向字典中添加一组键值对

dic2 = {    
    "name": "七夜老师", 
    "age": 18,   
    "cls": 234,   
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2['addr'] = "湖南长沙" 
print(dic2)  
# {'name': '七夜老师', 'age': 18, 'cls': 234, 'students_name': ['二师兄', '千寻', '听风、', '自由'], 'addr': '湖南长沙'}
字典的修改

-- 字典的变量名称["字典中存在的key"] = 新值---把原有字典的value换成新的

dic2 = {   
    "name": "七夜老师",   
    "age": 18,  
    "cls": 234,  
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2['age'] = 20 
print(dic2)

提问:把 自由 的值,改为 小玉 ?

dic2 = {  
    "name": "七夜老师",   
    "age": 18,    
    "cls": 234,   
    "students_name": ["二师兄", "千寻", "听风、", "自由"] }
dic2["students_name"][3] = "小玉" 
print(dic2)
字典的删除 -- pop()

不能为空,需要传入删除的key

错误的示例:

dic2 = {  
    "name": "七夜老师",  
    "age": 18,   
    "cls": 234, 
    "students_name": ["二师兄", "千寻", "听风、", "自由"] }
dic2.pop()  # pop expected at least 1 argument, got 0

正确的示例:

dic2 = {   
    "name": "七夜老师",  
    "age": 18,  
    "cls": 234,  
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2.pop("age")
print(dic2)  # {'name': '七夜老师', 'cls': 234, 'students_name': ['二师兄', '千寻', '听风、', '自由']}
字典的删除 -- popitem()

从后往前删出

dic2 = {  
    "name": "七夜老师",
    "age": 18,   
    "cls": 234, 
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2.popitem() 
print(dic2)  # {'name': '七夜老师', 'age': 18, 'cls': 234}

问题:当dict中所有的key都被删除了,还剩下什么?

dic2 = {    
    "name": "七夜老师",  
    "age": 18,  
    "cls": 234, 
    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2.popitem() 
dic2.popitem() 
dic2.popitem()
dic2.popitem()
print(dic2)  #  {}
字典的清空 -- clear()
dic2 = {    "name": "七夜老师",    "age": 18,    "cls": 234,    "students_name": ["二师兄", "千寻", "听风、", "自由"] } 
dic2.clear()
print(dic2)  #  {}

转义字符:键盘上有部分键,不能在代码里显示, 用英文去代替特殊键位

五、for循环和切片

循环

特征:遍历、循环

遍历:复杂的数据结构中,将里面的元素一个个的获取出来

循环:自带循环的效果,循环的次数由可遍历数据的长度来决定

语言结构:

for 变量名 in 可遍历的数据:  # 变量名:自定义的变量名(可以获取到每次循环的元素); 可遍历的数据包含:列表、字符串... ...    
    循环体的代码:每循环一次,执行一遍循环代码

通过for循环直接读取

lst1 = [1, "七夜老老师", 3, "a", "b", 6] 
for i in lst1:   
    print(i)

小测验:

# 此时,打印的i的值为多少?
j = 0  # 初始值 
for i in lst1:     
    if j % 2 == 0:  # j取值的范围为多少:0,2,4      
        print(i)           
        j += 1  # j每次循环都递增1 
 # 答案:1, 3, "b"

迭代器:range() 用于生成一个整数的序列,提供一个数字,自动生成一个序列列表(规则:左闭右开) -- 可迭代的对象

r = range(10) 
print(list(r))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
r1 = range(8) 
print(list(r1))  # [0, 1, 2, 3, 4, 5, 6, 7]

range()可以设置初始值,如过不设置,默认为0,如果设置了,只能够取到初始值到结束值之间的内容 -- 左闭右开

示例:

r2 = range(1, 10)
print(list(r2))  # [1-9]
r3 = range(8, 9) 
print(list(r3))  # [8]

range()结合for循环进行使用:

for i in range(10):  # [0-9]   
    print(i)

小测验:

# 问题1:for循环不能够遍历非可迭代的数据,比如:int类型 
# for i in 10:  # 'int' object is not iterable
#     print(i)
# 问题2:for循环可以遍历str类型?str类型是可以当做列表
for i in "七夜老师":  
    print(i)    
# 问题3:如果range()的开始值和结束值为同一个的话,能否取到值?
r4 = range(8, 8)
print(list(r4))  
# [] 无法同时满足两个条件,则取不到值

双重for循环

for循环的嵌套

示例:

# k = 0  # 初始值 
# 
# for i in range(1, 10):
# [1-9] 
# 
#     for j in range(1, 10):
#         k += 1  
# 每循环一次,k都会递增1 # 
# print(f"k此时的值为:{k}") 
# 当第一层for循环,循环1次的时候,里面这个for循环,循环几次?
# i每循环1次,都会让j循环9次,i最终会循环9次,就会导致双重for循环的最终循环次数:9 * 9 = 81

小测验:

 笔试题:打印九九乘法表 
    1 * 1 = 1 
    1 * 2 = 2, 2 * 2 = 4 
    1 * 3 = 3, 2 * 3 = 6, 3 * 3 = 9 
    ... 
    1 * 9 = 9, 2 * 9 = 18, 3 * 9 = 27 
    ... 

正确的写法和思路:

# print("{} * {} = {}".format(1, 2, 1 * 2)) 
# 定义了两个变量,一个是i,一个是j,总共的循环次数为81次
for i in range(1, 10):  # [1-9] 
    for j in range(1, i+1):  # [1 - 9]      
        print("{} * {} = {}".format(j, i, i * j), end=' ')  # 防止换行      
# 问题:当循环到第几次的时候,要求换行?
	print()  # 这个print放在哪个循环里面?j?i? -- i 
# 当 i = 1 , 此时 j = [1-9],j循环打印的时候,有没有换行? -- j是不进行换行 
# 核心点1: 
# 谁负责纵向的循环,谁负责横向的循环?
# j:横向,i:纵向
# 核心点2:
# 出现了多余的数据,应该修改谁的取值范围? -- j # i = 1, j循环9次,实际的需求:1次
# i = 2,j循环9次,实际的需求:2次
# i = 3,j循环9次,实际的需求:3次 
# i = 4,j循环9次,实际的需求:4次 
# i = 5,j循环9次,实际的需求:5次
# i = 6,j循环9次,实际的需求:6次 
# 核心点3: 
# 怎么修改j的取值 
# i和j的初始取值都是一样的,那么j的取值范围range()的开始值不改变
# i = 1 的时候,j的取值range(1, 2)才可以取到值1
# i = 2 的时候,j的取值range(1, 3)才可以取到值1, 2 # i每次递增,那么j的range(1, i+1)

查看源码**:Ctrl + 鼠标左键 点击你要查看的函数/方法内容**

print的源码:

因为print里面有\n,那么就表示print方法执行的时候,会自动换行

切片操作

列表的切片

列表的切片:分割一个列表,只提取其中某一个片段出来

语法规则:列表的变量名称[start:end:step]

start:开始值,从哪个地方开始

end:结束值,从哪里结束

step:步长,每隔几个元素获取一次值,默认值:1,可以省略,但是不能为0,否则就会报错

示例:

lst1 = [100, 3.14, True, "Huace", [1, 2, 3, 4]] 
# 根据下标取值
# print(lst1[1]) 
# 切片取值:
# print(lst1[0:2]) # start:end,[100, 3.14] 
# print(lst1[1:2]) # 结果:[3.14] 
# print(lst1[1:4])  # [3.14, True, 'Huace']
# 问题:获取 True, "Huace" 的值,怎么写? 
# print(lst1[2:4]) 
# print(lst1[0:-1])  # 行不行?可以,[100, 3.14, True, 'Huace'] # print(lst1[:3])  # start 省略 # print(lst1[1:])  # end 省略 # print(lst1[0::2])  # 每隔几个元素,取一次值 print(lst1[0::0])  # slice step cannot be zero

切片的赋值方式,切记不要变量直接赋值变量

lst2 = [1, 2, 3, 4] 
lst3 = lst2  # 变量赋值变量的操作 
# print(lst3) 
# print(lst2) # 隐患问题存在,如果给lst3中添加一个元素,那么lst2的元素是否会发生变化? -- 相等,安全性问题 
lst3.append(5) 
print(lst3)
print(lst2)

统计数据中元素的个数,count(元素具体值) -- 判断这个元素在我们列表中有几个

一个萝卜一个坑,判断的是最外面的数据中,有几个目标元素

lst1 = [100, 3.14, True, "Huace", [1, 2, 3, 4, True, True], [True, True]] 
print(lst1.count(True))
字符串的切片

str类型可以当做列表

语法规则:列表的变量名称[start:end:step]

start:开始值,从哪个地方开始

end:结束值,从哪里结束

step:步长,每隔几个元素获取一次值,默认值:1,可以省略,但是不能为0,否则就会报错

示例:

str1 = "hello python"
# res = str1[0]
# print(res) 
# res1 = str1[5]  # 空格也是一个元素
# print(res1) 
# 负数取值,倒过来取值,取第几个 
# res2 = str1[-1]
# print(res2)
# for i in str1:
#     print(i)
# str类型的切片 
# res3 = str1[0:3:2] 
# print(res3)

Project_Duck(烤鸭店项目)

project_duck_4.1:

print("欢迎使用七夜老师的烤鸭店利润计算器!")
projects = {} 
while True:  # 让系统可以循环使用,不用每次都手动执行   
    # 提供一个可选择功能的菜单  
    oper_type = input("请输入对应的数字进行功能选择:\n1.录入商品的功能\n2.查询商品的功能\n3.退出系统的功能\n")    
    if oper_type == "1":      
        # 1.录入商品的功能       
        pro_list = []  # 定义一个空列表        
        # 1) 把input里面的str数据,放在一个列表中        
        load_txt = ['请输入你的商品名:', "请输入你的成本价:", "请输入你的产地:", "请输入你的生产日期:", "请输入商品的属性a: ", "请输入商品的属性b: "]         
        # 2) 把列表中的str数据,通过for循环,依次放在input中       
        # for i in load_txt:     
        #     input(i)       
        # 3) 在通过变量的重定义,重新赋值定义一个变量,用来接收input每次循环时所接收的值       
        # for i in load_txt:  
        #     load_name = input(i)         # 4) 把接收的值,依次添加到pro_list列表中       
        for i in load_txt:           
            load_name = input(i)           
            pro_list.append(load_name)         # 问题:怎么把pro_list的值,加到projects里面去?        
            # projects.append(pro_list)      
            projects[pro_list[0]] = pro_list  
            # key的值应该用哪个?给商品名称,value给整个商品的属性列表  
        elif oper_type == "2":  
            # 2.查询商品的功能      
            # 如果想自己输入查询的商品名称进行查询 -- 根据key的名字查询对应的value        
            print(projects)      
            # 用户自己输入查询的商品名称      
            po_name = input("请输入您要查询的商品名称:")     
            print(f"您查询到的商品信息为: {projects[po_name]}")    
        elif oper_type == "3":        # 3.退出系统的功能        
            break  # 直接跳出整个循环     
        else:       
            print("系统无法识别你的输入,请重新选择!")      
            continue  # 跳出当前循环,重新判断条件

回退缩进:shift + tab

六、 元组、集合和函数的定义与返回值

元祖

元组的定义

元组的数据结构跟列表相似

特征:有序、不可变

  1. 有序:有(索引/下标/index) 正序、反序

  2. 标识符: ( ) 里面的元素是用英文格式的逗号分割开来

  3. 关键字:tuple

面试中常问的问题:列表和元组有什么区别?

元组是不可变的:程序在运行的时候,无法对其进行改变 -- 没有提供关键字、方法去操作它,没有增删改的操作

问题:既然无法对其进行变化,那么为什么要有元组的存在?

安全性考虑 -- 国内的省份(省、市) 变量,常量

但凡是可以进行操作的数据,都存在安全隐患

示例:

 tp = ()  # 定义一个空元组 
 print(type(tp))  # <class 'tuple'>
 tp1 = (1, 2, 3, 4, 5)  # 定义一个有值的元组 
 print(tp1)

元组的基本查询,根据下标

 tp1 = (1, 2, 3, 4, 5) 
 print(tp1[0])

元组为什么不可以进行变化(不是指的手动修改代码)

列表修改示例:

 lst1 = [1, 2, 3, 4]
 num = 0  # 初始值
 while True:     
     if num > 5:      
         lst1.append(5) 
      time.sleep(2)  # 强制等待的时间,单位:秒    
     print(f"此时lst1的实际长度为: {len(lst1)}")     
     num += 1  # 每循环一次叠加1
     # 问:当数据为lst1的时候,发生长度变化之前,是循环了几次? 6次

元组修改示例:

 import time
 lst1 = [1, 2, 3, 4]  # 列表是可以提供变化的
 tp1 = (1, 2, 3, 4)
 num = 0  # 初始值 
 while True:    
     if num > 5:     
         tp1.append(5)  # 报错:'tuple' object has no attribute 'append'    
      time.sleep(2)  # 强制等待的时间,单位:秒    
      print(f"此时lst1的实际长度为: {len(tp1)}")     
       num += 1  # 每循环一次叠加1     # 问题2:既然列表是可以在程序执行之间进行操作,那么换成元组行不行?

问题1:res是由tp1 和 tp2 拼接在一起的,还是额外生成的? -- 额外生成的一个新元组

 tp1 = (1, 2, 3, 4) 
 tp2 = (100, 3.14)
 res = tp1 + tp2 
 print(res) 
 print(type(res))

问题2:元组乘以int类型的数字的res1是打印两次tp1,还是额外生成一个新的元组?

 tp1 = (1, 2, 3, 4) 
 tp2 = (100, 3.14)
 res1 = tp1 * 2 
 print(res1)
 print(type(res1))

小测验:如果给你一个元组,需要修改这个里面的数据,怎么做? -- 先转换成列表,修改数据,然后在转化成元组

 tp1 = (1, 2, 3, 4)
 # 获取修改之前的内存地址 
 print(f"修改之前的内存地址: {id(tp1)}")
 # 1.先转换成列表 
 lst1 = list(tp1)
 # print(lst1) 
 # print(type(lst1))
 # 2.修改数据 
 lst1.append(5) 
 # print(lst1)
 # print(type(lst1)) 
 # 3.然后在转化成元组
 tp1 = tuple(lst1)
 # 变量的重定义 -- 对变量进行重新赋值
 # print(tp1) 
 # print(type(tp1)) 
 # 获取修改之后的内存地址 
 print(f"修改之后的内存地址: {id(tp1)}")
 # 问题:修改之前的tp1的内存地址和修改之后的一样么? 不一样,是一个新的元组,只是引用的变量名称是一样的,但是存放的内存地址不一样

问题:谁是元祖类型? -- 每个元素都是需要用逗号分隔开来的

 num1 = (1,) 
 num2 = (1)
 print(type(num1))  # <class 'tuple'> 
 print(type(num2))  # <class 'int'>

集合

集合的定义

定义:由不同的元素组成的一个数据结构,无序排列的

标识符:{ }

关键字:set

特征:无序,元素不能重复,集合和集合之间可以做运算

单个元素的集合定义

 set2 = {1,} 
 print(type(set2))

无序排列 -- 存放在内存地址之前是无序的

 set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"}
 print(type(set1))  # <class 'set'>
 print(f"猜一猜,set1集合中的第一个值是? {set1}")
 print(f"第二次打印无序的集合:{set1}")
 print(f"第三次打印无序的集合:{set1}")
 ​
 # 随机的结果:
 <class 'set'>
 猜一猜,set1集合中的第一个值是? {'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'}
 第二次打印无序的集合:{'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'}
 第三次打印无序的集合:{'欢迎', '来到', '老师', '课堂', '的', '!', '七夜'}

集合里面的元素不能重复 -- 自动去重

set2 = {"七夜老师", "三丰老师", "小明老师", "长风老师", "哈米老师", "七夜老师", "三丰老师"}
print(set2)  # {'三丰老师', '哈米老师', '小明老师', '长风老师', '七夜老师'}
集合的操作

进行强制转换

set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"}

lst1 = list(set1)
print(type(lst1))
print(f"lst1中的第一个值:{lst1[0]}")  # 不确定、随机的

问题:如果转换完成后,连续打印,第一次的值和后面N次的值,是一样的么?

答:一样的,原理:存放内存地址之前,是随机的,但是一旦存放了,后续的内容都是固定的

set1 = {"欢迎", "来到", "七夜", "老师", "的", "课堂", "!"}

lst1 = list(set1)
print(type(lst1))
print(f"lst1中的第一个值:{lst1[0]}")  # 不确定、随机的
print(f"lst1第二次打印第一个值:{lst1[0]}")
print(f"lst1第三次打印第一个值:{lst1[0]}")
print(f"lst1第四次打印第一个值:{lst1[0]}")

集合的添加 -- add()

set1.add("2024") 
# print(set1)

集合的删除 -- pop(随机删除,因为没有下标)、remove(删除指定的值)

# set1.pop()  # 随机删除,因为没有下标
# print(set1)

# set1.remove("七夜")  # 删除指定的值,如果删除不存在的值,会报错
# set1.remove("七夜")
# print(set1)

set1.discard("老师")  # 提前准备好,想删除的值,删除多次,都不会报错
set1.discard("老师")
print(set1)
集合的运算

运算的方式:交集、并集、差集、交叉补集

交集:获取两个集合之间相同的部分 -- intersection

set1 = {"七夜老师", "小明老师"}
set2 = {"七夜老师", "长风老师"} 
print(f"获取两个集合之间相同的部分: {set1.intersection(set2)}")
# 获取两个集合之间相同的部分: {'七夜老师'}

并集:合并两个集合,自动去重 -- union

set1 = {"七夜老师", "小明老师"} 
set2 = {"七夜老师", "长风老师"}
print(f"合并两个集合,自动去重: {set1.union(set2)}")

差集:获取集合中,另一个集合没有的内容 -- difference

set3 = {"七夜老师", "高", "富", "帅"}
set4 = {"小明老师", "高", "矬", "富"}

print(f"获取对方有,但是自己没有的元素: {set3.difference(set4)}")

交叉补集:剔除公有的内容,留下双方独有的内容

set3 = {"七夜老师", "高", "富", "帅"}
set4 = {"小明老师", "矮", "矬", "穷"}

print(f"剔除公有的内容,留下双方独有的内容: {set3.symmetric_difference(set4)}")

函数

函数的定义

定义:将一段公式/逻辑代码定义在一个特定的标题(函数名称)下,通过一块,或者一行代码来执行固定好的逻辑,而这些代码只有函数被调动的时候才会执行

通俗点:封装一些代码

核心点:函数的定义、函数的调用

函数的定义:封装好的代码,只有在调用的时候,才会执行 -- 定义函数的时候,不会执行函数内部的代码

函数的调用:语法:函数的名称() -- 调用函数,执行函数内部的代码

函数定义

语法规则:

def 自定义的函数名称():  
	封装的代码 ... ...

定义函数,如果不进行调用,是不会运行函数内部的代码(注意:自定义的函数名称,不要和python关键字、已存在的函数名称重复)

# 示例:线性脚本
# m = 1
# n = 2
# s = m + n
# print(f"m + n 的结果:{s}")

# 封装之后,不再是简单的线性脚本

def add1():  # 函数的名称: add1
    # 需要封装的代码
    m = 1
    n = 2
    s = m + n
    print(f"m + n 的结果:{s}")

调用函数 -- 函数的名称() 表示调用函数,也就是执行函数的内部代码

def add1():  # 函数的名称: add1
    # 需要封装的代码
    m = 1
    n = 2
    s = m + n
    print(f"m + n 的结果:{s}")

# 调用函数 -- 函数的名称() 表示调用函数,也就是执行函数的内部代码
add1()

函数的参数

定义函数的时候,可以在小括号里面定义一些参数

定义的参数,可以不给值,然后在调用函数的位置,进行传参

def demo1(name, age, addr):
    print(f"""
        =====demo1函数里面的参数=====
        name: {name}
        age: {age}
        addr: {addr}
    """)

位置参数:按照固定的位置进行传参

def demo1(name, age, addr):
    print(f"""
        =====demo1函数里面的参数=====
        name: {name}
        age: {age}
        addr: {addr}
    """)

demo1("七夜老师", 18, "湖南长沙")

指定参数:指定固定的参数进行传参

def demo1(name, age, addr):
    print(f"""
        =====demo1函数里面的参数=====
        name: {name}
        age: {age}
        addr: {addr}
    """)

demo1(age=18, name="七夜老师", addr="湖南长沙")

默认参数:定义函数的时候,可以设置参数的默认值 -- print函数里面的end='\n'

# def demo2(name="小明老师", age=88, addr=None):
#     print(f"""
#             =====demo1函数里面的参数=====
#             name: {name}
#             age: {age}
#             addr: {addr}
#         """)
#
#
# demo2(addr="湖南长沙", name="七夜老师")

问:默认参数是要么都传,要么就都不传吗?

答:定义函数的时候,如果给部分参数设置了默认值,那么非默认参数也要遵循默认参数的规则,否则得把非默认参数写在默认参数前面

不定长传参:单个*号 和 两个*号

单个*号的参数:args是默认的名称,可以随意修改 -- 元组类型

# def demo3(*args):
#     print(f"获取到的值:{args}")
#     print(f"获取值的类型: {type(args)}")
#     print(args[0])
#
#
# demo3(1, 2, 3, 4, 5)

两个*号:kwargs是默认的名称,可以随意修改 -- 字典类型

# def demo4(**kwargs):
#     print(f"获取到的值:{kwargs}")
#     print(f"获取值的类型: {type(kwargs)}")
#
#
# demo4(name="七夜老师", age=18, addr="湖南长沙")
函数的返回值

注意事项:

1.函数的内部可以写return返回值,或者不写

2.如果不写return,也可以执行,不会报错,但是接收到的值,还是 None

3.如果写了,可以把需要传递的值,传递给调用函数的地方,通过两种方式获取(print、变量)

4.写了return但是没有传值的情况下,获取到的值是 None

5.如果有return返回值的情况下,可以通过两种方式获取

# def add1():  # 函数的名称: add1
#     # 需要封装的代码
#     m = 1
#     n = 2
#     s = m + n
#     print(f"m + n 的结果:{s}")
#
#
# add1()

# 想获取s的值,然后进行 + 100的操作?
# print(s + 100)  # 函数的作用域问题 -- 后面的课程会讲,暂时不讲

# def add2():
#     m = 1
#     n = 2
#     s = m + n
#     # 不直接写print,因为无法传递数据
#     # 通过函数的返回关键字return,把数据传递给调用函数的地方
#     return s


# add2()
# 问题:此时调用函数,会不会打印s的值? -- 不会
# 因为:没有对获取到的s值,进行打印操作

# 方式一:直接通过print打印获取到函数返回值
# print(f"获取到函数内部的s:{add2()}")

# 方式二:通过变量接收函数的返回值,然后进行后续的操作
# res = add2()
# print(f"res + 100的值:{res + 100}")
 # 写了return但是没有传值的情况下,获取到的值是 None
# def add3():
#     m = 1
#     n = 2
#     s = m + n
#     return

# 如果不写return,也可以执行,不会报错,但是接收到的值,还是 None
# def add4():
#     m = 1
#     n = 2
#     s = m + n
#
#
# # 方式一:
# print(add4())
#
# # 方式二:
# res = add4()
# print(res)

# lst1 = [1, 2, 3]
# print(lst1.extend("七夜"))

课后作业

遇到的问题
1、pycharm中输入代码后会出现闪动的黑白方块

在键盘中点击一次“insert”键则会自动消失

2.获取两个数的最大值
max(num1,num2)
3.函数内部的变量需要定义后使用 (suum=0)
 def sum(*args):
    suum=0
     for i in args:
         suum = suum +i
         return suum
4.return不打印返回值,print会打印返回值
5.""" """,可以是注释也可以是多行字符串输出

七、函数相关知识

函数的注释与嵌套

函数的注释

函数的注释与普通注释的区别:用来说明当前函数的参数含义

param 参数名: 参数的注释信息

return: 函数的返回值

 def fun1(name):
     """
     :param name: 参数的注释信息
     :return: 函数的返回值
     """
     print("fun1函数")  # 查看源码的快捷键:Ctrl + 左键 点击要查看的函数
 ​
 ​
 def fun2(name, age, addr, sal):
     """
     :param name: 请输入姓名
     :param age: 请输入年龄
     :param addr: 请输入地址
     :param sal: 请输入薪资
     :return: 函数执行后的返回信息
     """
     print("fun2函数")
     
 # fun1()
 # fun2()
 ​
 # lst1 = [1, 2]
 # lst1.append()

示例二:

def login(user, password):
    """
    :param user:  请输入登录的用户名
    :param password:  请输入登录的密码
    :return:  返回账号信息校验的结果:True/False
    """
    if user == 'admin' and password == '123456':
        return True


# print(login(user='admin', password='123456'))
# login()

# 打印函数的注释
print(login.__doc__) 
print(print.__doc__)
函数的嵌套

一个函数的内部调用另一个函数

# def fun1():
#     print("欢迎来到七夜老师的课堂!")
#     fun2()  # 陷入死循环的情况
#
#
# def fun2():
#     print("VIP 234 班级的直播课!")
#     fun1()  # 调用fun1函数
#
#
# # 问题:想在调用fun2函数的同时,去调用fun1函数?
# fun2()  # 调用fun2函数

一个函数内部嵌套另一个函数

def fun3():
    print("欢迎来到七夜老师的课堂!")

    def fun4():
        print("VIP 234 班级的直播课!")

    fun4()


# 问题1:运行fun3函数,会打印几句话?
# fun3()
# 如果不调用函数,是不会去运行函数的内部代码的!!!

# 问题2:能不能在最外层,调用fun4函数?
# fun4() # name 'fun4' is not defined
# 在函数的内部定义的函数,不能直接在最外层调用 -- 函数的作用域

# 问题3:那么怎么去调用fun4函数呢?
# 应该在fun4函数定义的同级
fun3()

python中的内置函数

作用域函数

作用域:定义的变量和函数在哪个范围内可用

文件和文件之间定义的东西,一般不能直接用

函数内定义的东西,不能在文件中直接使用,哪怕同一个文件也不行

类中定义的东西,只在类的内部生效,不能在文件中直接使用

变量:

全局变量 -- 在当前文件内定义的变量,可以在文件任何地方使用

局部变量 -- 在有效范围内可以调用,出了范围就不能用了

类声明的变量也是一样,类的概念后面再说(8节课)

局部变量在定义的时候可以直接声明为全局变量

# def fun1():
#     a = 10


# 问题1:能不能再最外层,直接引用变量a?
# print(a)  # name 'a' is not defined
# 不可以直接引用

# 全局变量

# a = 10  # 定义了一个全局变量a
#
#
# def fun2():
#     b = 5  # 局部变量
#     # print(a)
#     print(b)
#
#
# # print(a)
# fun2()


# 问题2:b变量的作用域是fun2函数的内部
# print(b)

# 问题3:如果想把函数内部的局部变量的值,传递到函数的外部进行使用?
# def fun3():
#     s = 20
#     return s  # 返回函数的数据、结果给到调用函数的位置
#
#
# s = fun3()
# s1 = s + 100
# print(s1)

# 问题4:如果想传递多个的函数内部的参数,怎么办?
# def fun4(name, age, addr, sal):
#     return name, age, addr, sal
#
#
# name, age, addr, sal = fun4(name="七夜老师", age=18, addr="湖南长沙", sal=500)
# print(f"""
#     =====自我介绍=====
#     name: {name}
#     age: {age}
#     addr: {addr}
#     sal: {sal}
# """)

局部变量定义成全局变量

通过global关键字,先声明变量,然后再去赋值

# def fun6():
#     b = 5  # 未声明
#     global c  # 已声明
#     c = 6
#
#
# fun6()
# # 哪怕是通过global关键字,转化成全局变量,也不可以直接使用,必须使声明的代码(所在的函数)被执行 (注意)
# print(c)

在while里面,定义的全局变量,可以进行变量的重定义

e = 10
while True:
    e = 5
    break
print(e)如果在循环内部重新定义这个变量,那么这个全局变量的值就被改变了

# 问题:e最后打印的值?
a = 1
a = 2
print(a)
数学函数

abs() 绝对值

divmod() 返回商和余数

round() 四舍五入(银行家算法)

pow() 次方

sum() 求和

min() 最小值

max() 最大值

abs() 绝对值

print(abs(-1))  # 1

divmod() 返回商和余数

# x = int(input("请输入一个整型:"))
# a, b = divmod(x, 2)
# print(f"商:{a}")
# print(f"余:{b}")

round() 四舍五入(银行家算法)

奇数:四舍五入,偶数:直接舍去(这个规则,只在0.5区间生效)

# print(round(1.5))  # 2
# print(round(3.5))  # 4
# print(round(5.5))  # 6
#
# print(round(2.5))  # 2
# print(round(4.5))  # 4
# print(round(6.5))  # 6

# print(round(4.9))
# print(round(4.6))
# print(round(4.51))

pow() 次方

print(pow(10, 2))

sum() 求和

lst1 = [1, 2, 3, 4, 5, 6, 7] print(sum(lst1))

min() 最小值

 print(min(lst1))

匿名函数

匿名函数的定义

匿名函数:就是没有名字的函数

python lambda表达式实现匿名函数

语法规则:

lambda 参数: 逻辑

匿名函数里面的参数名称,是自定义

结果就是返回表达式的结果

示例一:

 import math  # 导入
 ​
 ​
 # pai = math.pi
 # print(f"圆周率π: {pai}")
 #
 # # 圆的面积计算公式: s = π * r²
 # r = 5  # 圆的半径
 # s = math.pi * pow(r, 2)
 # print(f"圆的面积: {s}")
 ​
 ​
 # 方式一:普通的函数定义
 def s_area(r):
     """
     :param r: 圆的半径
     :return: 返回圆的面积
     """
     s = math.pi * pow(r, 2)
     return s
 ​
 ​
 print(f"当r的值为5的时候,圆的面积: {s_area(r=5)}")
 ​
 # 方式二:匿名函数的定义
 res = lambda r: math.pi * pow(r, 2)
 print(f"当r的值为5的时候,圆的面积: {res(r=5)}")
匿名函数的使用
 lst1 = [10, 20, 30, 40] 
 res1 = lambda a: min(a)
 print(f"获取lst1列表中的最小值:{res1(a=lst1)}")

装饰器之函数传递

函数的传递

python中可以把函数当变量传递

所以这种情况下,可以直接执行被传入的函数

主题:函数的引用 和 调用

示例一:

 # def fun1():
 #     print("欢迎来到七夜老师的课堂!")
 ​
 ​
 # 函数的调用 -- 函数的名称(),就会执行函数的内部代码
 # fun1()
 ​
 # 函数的引用(所在的内存地址) -- 函数的名称,没有小括号
 # print(fun1)
 # <function fun1 at 0x7fbb180c8160>, function代表是一个函数、fun1表示函数的名称、at 0x7fbb180c8160表示函数所在的内存地址
 ​
 # 问题:函数的调用,与函数的引用之间有什么区别?
 # 函数的调用有小括号,函数的引用没有小括号

示例二:

def fun1():
    print("欢迎来到七夜老师的课堂!")


def fun2(fun_name):  # 参数的名称可以自定义
    """
    :param fun_name: 传入函数的引用/本体
    :return: 调用传入的这个函数
    """
    print("这里是VIP 234 班级的直播课堂!")
    print(f"此时fun_name获取的值:{fun_name}")  # fun1函数的引用 -- 引用与调用之间的区别:有没有小括号

    fun_name()  # 请问:这是在调用哪个函数? -- 调用fun1函数


# 通过函数的引用,来完成,调用fun2函数的时候,去调用fun1函数
fun2(fun_name=fun1)  # 把fun1函数,当做变量进行传值
调用

运行这个函数的内部代码

引用

提供这个函数所在的内存地址,然后加上小括号,就可以完成对这个函数的调用

口诀:有小括号叫调用,没有小括号叫引用

在引用函数的时候,不会因为没有传参,而报错

但是在调用函数的时候,会因为没有传参,而报错

 def login(username, password):
     print(f"""
         ===用户信息===
         username: {username}
         password: {password}
     """)
 ​
 ​
 def fun1(fun_name, value1, value2):
     print("fun1函数")
     fun_name(value1, value2)
 ​
 ​
 fun1(fun_name=login, value1="admin", value2="123456")

八、装饰器、模块和文件操作

装饰器的详解

日志

程序运行的时候的记录 -- 日志

在实际工作中,python这样的东西,是放在服务器(linux)上运行的

日志其实就是记录下来当前程序的运行,协助我们定位问题

确定问题的方式(通过日志、报错信息去溯源)

 import logging  # 日志模块

日志模块,会有日志的级别定义

常见的日志级别:

warning:警告---warning和error

error:报错---error

debug:调试---都有

info:正常---没有debug

# 级别是自己设置:我们可以通过自定义级别去确定什么东西该被记录,什么东西不被记录

# 设置的级别,会打印自己以及比自己小的级别信息!!!

# DEBUG > INFO > WARNING > ERROR

logging.basicConfig(level=logging.DEBUG)

日志打印

# logging.info("自定义的info级别的输出内容")
# logging.debug("自定义的info级别的输出内容")
# logging.warning("自定义的info级别的输出内容")
# logging.error("自定义的info级别的输出内容")

日志输出和print打印有一些区别:

# 1.颜色不一样

# 2.语法不一样

# 3.日志打印的时候,会带有用户信息

注意事项:控制台里面的打印,有可能是日志在前,也有可能是print在前(日志和print打印的输出级别没有先后顺序 -- 并行)

 def log_info(fun_name):
#     logging.info("---->日志开始记录<----")
#     fun_name()
#     logging.info("---->日志结束记录<----")


# log_info()

# def fun2():
#     print("fun2函数的代码运行!")


# 问题:想通过把函数当做变量传值的方式,运行日志函数的时候,也能过打印fun2函数,并且print的信息要放在日志打印的之间?

# 1.调用log_info函数
# log_info()

# 2.给log_info函数设置参数,用来接收fun2的函数本体

# 3.需要把fun2的函数本体,当做变量传递给log_info的参数fun_name
# log_info(fun_name=fun2)

# 4.把接收进来的fun2函数本体,在日志打印之间进行调用,也就是fun_name()
装饰器

可以在原有的函数之前、之后进行代码的补充(强化)

语法规则:

def 外层函数(设置一个参数,用来接收调用函数的本体):
    
    def 内置函数():
        你要添加的前/后的代码补充
    
    return 内置函数的名称

普通的函数嵌套

# def zsq():
#
#     def nzhs():
#         print("nzhs的打印信息")
#         # pass  # 让程序直接跳过这部分的代码,也不报错
#
#     nzhs()
#
#
# zsq()

示例:

# def log_zsq(fun_name):
#     def log_info():
#         # print(f"fun_name的值:{fun_name}")  # <function fun3 at 0x7fb7d017d430>
#
#         # 既然fun_name的值是fun3函数的本体,那么只要添加一个括号,就可以运行fun3函数的代码
#         # fun_name()
#
#         print("1")
#         fun_name()
#         print("2")
#
#     return log_info
#
#
# @log_zsq
# def fun3():
#     print("fun3函数的打印信息!")
#
#
# fun3()

# 问题:在不改变fun3函数里面的代码同时,在他的前面/后面加一些代码,怎么办?
# 例如:在前面加一个打印"1",在后面加一个打印"2"

# 1.在原有函数的头部,添加一个@符号,然后跟着装饰器的函数名称(不要带括号)

# 2.获取fun_name的值,应该是什么? -- fun3函数的本体

# 3.调用fun3函数

# 4.按照需求,完成代码的补充

装饰器的传参

# def login_zsq(fun_name):
#     def login_nzhs(username, password):
#         print(f"username:{username}")
#         print(f"password:{password}")
#
#         # if username == "admin" and password == "123456":
#         #     print("账号验证成功,允许登录")
#
#         fun_name(username, password)  # 此时在调用fun4函数,但是fun4函数定义了两个参数,并未传值
#
#     return login_nzhs


# @login_zsq
# def fun4(username, password):
#     if username == "admin" and password == "123456":
#         print("账号验证成功,允许登录")


# fun4(username="admin", password="123456")

# 调用装饰器的时候,第一次传参,先给谁?
# 装饰器里面的内置函数,需要定义参数用来接收

# 既然内置函数可以接收值,那么原函数fun4怎么接收传进来的值?
# 在装饰器里面调用原函数执行的时候,把参数同时传递给他

知识点检查

"""
1.定义装饰器的规则
2.怎么调用/使用装饰器
3.怎么接收调用原函数时,传入的值
4.原函数,怎么接收传进来的值
"""


# 1.定义装饰器的规则
def login_zsq(fun_name):
    def login_nzhs(username, password):
        print(f"username: {username}")
        print(f"password: {password}")

        if username == "admin" and password == "123456":
            print("账号识别成功,允许登录!")

            user = "七夜老师"
            sex = "man"
            age = 18

            fun_name(user, sex, age)

    return login_nzhs


# 2.怎么调用/使用装饰器
@login_zsq
def fun1(user, sex, age):
    print(f"""
    =====自我介绍=====
    user: {user}
    sex: {sex}
    age: {age}
    """)


# 3.怎么接收调用原函数时,传入的值
fun1(username="admin", password="123456")

# 4.原函数,怎么接收传进来的值

# 如何打断点,怎么调试代码

# 手动设置中断程序运行的节点 -- 断点

# 断点调试,只生效于DEBUG模式

模块

模块的概念

包(package)和模块(module)

包就是python中的文件夹(图标有小圆点、有一个init.py文件)

模块就是我们的文件名(不包含.py) 举例:模块的概念

示例:

import time  # 模块

# print(time.time())  # 当前时间的时间戳
# time.sleep(3)  # 强制等待x秒


# from 模块的路径  import ...
# from 包/模块 import 方法/函数/类/变量/其他的数据信息...

# from time import sleep
# from time import *

# sleep(3)

文件操作

文件读取

磁盘:C盘... 500G、1TB、4TB

内存:内存地址,临时存储的空间 16G、24G、32G、64G

python 能够直接读取计算机文件 -- txt、excel、docx、csv、yaml...

语法规则:

open('文件路径', mode='读取方式', encoding='编码格式')

mode: r 读取 w 写入 a 追加写入

直接copy的路径,容易存在转义字符的情况,在引号的前面加一个小写的 r -- 防转义

file = open(r'/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt',
            mode='r', encoding='utf-8')

# 读取文件 -- read()
# msg = file.read()
# print(f"读取到的内容:{msg}")

# 关闭文件 -- close()
# file.close()

# msg1 = file.read()
# print(f"读取到的内容:{msg1}")

# 问题:那么此时,msg还有没有值?可以的,因为变量的值已经存储在内存中了
# print(f"读取到的内容:{msg}")

# 按行读取 -- readline()
# msg2 = file.readline()
# print(f"读取到的内容:{msg2}")

# 读取所有的内容,按行划分列表元素 -- readlines()
# msg3 = file.readlines()
# print(f"读取到的内容:{msg3}")
# print(len(msg3))
文件写入

# w:覆盖写入

# a: 追加写入

示例:

file = open("/Volumes/attached/hcedu/vipCourse/pythonBasic/python_code/python_0307_234/day07/03 文件操作/load_txt1",
            mode="a", encoding="utf-8")

# w:覆盖写入
# a: 追加写入

# 直接写入 -- write()
file.write("这个是我想写入的内容\n")
file.write("这个是我想写入的内容\n")
file.write("这个是我想写入的内容")
file.write("这个是我想写入的内容")

file.close()  # 养成好习惯

九、异常机制处理

异常机制

try和except

异常:程序无法继续执行了,例如:字符串和数字相加,除以0,对None进行操作

中断当前程序执行,然后打印出红字Exception

error

捕捉异常的方式:关键字

 try:   
     代码块(逻辑) 
 except 异常类型(Exception):   
     代码块(出异常之后,会执行这里)

示例:

 str1 = input("请输入8个长度以外的字符串:") 
 try:
     print(f"获取输入字符串的第八个值:{str1[7]}")  
     # unexpected EOF while parsing except Exception as e:  
     # 获取异常的信息,然后赋值给变量 e  
     print(f"报错的异常为: {e},请检查!!!") 
     print("欢迎来到七夜老师的课堂!")

注意:

一旦try的代码块运行完成,没有报错,就不会去运行except

当str1没有8个长度的值出现,那么str1[7]的代码是不是会报错?会

可以提前设置异常处理机制,可以清晰的定位问题,并且不妨碍程序运行

获取报异常的信息,并且可以打印出来

try和finally
  1. try...except 捕获异常,出异常了执行except代码块的内容

  1. try...finally

 try:    
     代码块
 finally:    
     无论异常是否发生,finally代码块内容一定会执行

示例:

  try: 
      print("try下面的代码块执行!") 
      print("报错前的代码") 
      n = 1 / 0 
     # 一定会报错 
      print("报错后的代码")
  except: 
      print("except下面的代码块执行!") 
      n = 1 / 0 
  finally: 
      print("finally下面的代码块执行!") 
  #问题:try执行代码的时候,遇到了报错的代码,那么之前的代码是否会执行?会 
  #但是,报错后的同级代码,不会运行

注意:

  1. 无论try和except会不会报错,finally都会执行

  1. 只有try报错了,才会运行except

  1. 如果try报错,并且except里面也报错了,会同时打印报错信息

练习:

 try: 
     print("最外层 -- try代码块")     
     try:       
         print("里面 -- try代码块")      
         n = 1 / 0     
     except:       
         print("里面 -- except代码块")     
     n = 1/0 
 except:   
     print("最外层 -- except代码块")  
 # 问题:如果正常执行,会打印哪几行的代码?
 # 如果存在多个try、except的嵌套 -- 遵循try和except的运行逻辑,try不报错,就不会运行except
 # 问题:在最外层的try里面,加了报错代码,会打印哪几行? 
 # 一旦遇到报错的代码,就不会执行同级代码
 # 问题:在里面层的try里面,加了报错代码,会打印哪几行? 
 # 里面这层try、except已经做了正常的异常处理之后,就表示try已经全部运行成功
assert异常

断言:预期结果 == 实际结果

断言:用关键字 assert + 表达式(表达式返回一个bool值)

我希望是一个什么结果 -- 元素定位,assert 标签是否存在 True False

如果表达式是False,就会出异常,后面可以加提示

示例:

username = input("请输入登录的账号:") 
password = input("请输入登录的密码:") 
if username == "admin" and password == "123":
     print("欢迎成功登录七夜老师的用户系统!") 
assert username == "admin" and password == "123", f"Use case does not pass, please check data! username:{username}, passowrd:{password}"
print("欢迎成功登录七夜老师的用户系统!")

# 为什么用例需要用断言来做处理?
# 一条自动化用例,如果代码全部运行通过,没有报错,视为用例通过
# 反之,如果一旦报错,就视为用例失败

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值