python 编程入门 - 学习笔记(上篇)

前言

这段时间基本告别了摸鱼,认认真真在工作和学习上努力了一段时间,实际上这篇文章不太适合发在这里,毕竟鱼排的鱼油们个个都是高手,不然也挤不出时间摸鱼(笑~)

但是吧,自己学完的部分,总结好的笔记,放出来也更有意义

这篇笔记,是基于python编程从入门到实践(第二版)写成

得提前说明,我是个非科班,非计算机行业的,程序员,笔记上有很多幼稚的认识,请各位多多包涵,若有疏漏,请来鞭策我吧~

观前提示:python学习是基于我已有的perl知识写成,并不适合完全新手入门,有些知识点简略而过

这篇上篇,仅包含最基础的语法部分,不牵涉任何高级使用

hello,world

print("hello,world")

官网

https://www.python.org/

官方帮助文档地址

https://docs.python.org/zh-cn/

注释

# 使用#作为注释

"""
三引号之间的内容也是注释
多行注释
"""

数据类型

此条目完全可以参考C语言,使用type函数可以返回数据类型

无需理解,了解即可

不同函数需要不同类型的数据

print(type("123"))
  • 字符串(str)

    若要将一个数字转换为字符串,直接在前面加str转换

    a = 4
    print(str(a))
    
  • 整数(int)

    字符串转换为数值,使用int转换

    a = "3"
    a = int(a)
    print(a)
    
  • 浮点数(float)

  • 布尔类型(bool):TrueFalse

    t=True
    
  • 空值类型:空值并非false,就是空值,具体为None

    my_wife = None
    
  • 列表

  • 字典

字符串

#引号内就是字符串,也可以用单引号括住内容,不加引号就是变量
print ('test')

#可以用“+”号将字符串连接(如果需要与非字符串连接,则需要使用后续的变量内插功能)
print("我的"+"测试")

#python特性,读一行执行一行,因此想字符串直接换行,需使用三引号,否则换行必须使用\n
print('''今年是
高三一班
打扫卫生''')

#字符串转义,遇到特殊符号会陷入迷惑,需要使用反斜杠‘\’转义,或在前面加入r参数
print("\\ntest_2")
print(r"\ntest_2")

#如字符串包含双引号,使用反斜杠,也可以使用单引号括住字符串避免歧义
print("te\"xt_1")
print('tes"t_3')

特殊用法

字符串可以直接使用类似数组的方法提取字符串中的字符

可以为负值,则从后往前

print("123456"[2])
#输出的是3

print("123456"[-1])
#输出6

数字计算

python支持直接对数计算,数与运算符之间加空格不影响计算,也支持使用括号进行次序运算

print(2+3)
print(3 ** 2)
print((2+3)*4)
print(4 % 3)		#求模计算(余数)
#数较大时,加入下划线使得易于阅读,也不影响计算,结果不会出现下划线
print(1_0000_0000 *5)

#更多计算方式,使用函数库math
#导入函数库使用import
import math
print(math.sin(1))

注意,只要操作数是浮点数,以及除法,得到的结果也会是浮点数

变量

变量规范

命名不得以数字开头,不允许出现空格,通常来说只允许数字,下划线,字母三种组合

python同样不允许关键字作为变量名,你可以输入help("keywords")运行,来查看哪些为python关键字

特别的,Python3.x 已经支持全面 Unicode 编码,比如支持使用中文作为变量名

定义变量

message = "Hello Python world!"
print(message)

old_message = message
message = "Hello Python Crash Course world!"
print("message值:\n"+message)
print("old_message值:\n"+old_message)

#同时多个变量赋值
aa,bb,cc=1,2,3
print(aa)
print(bb)
print(cc)

技巧

赋值变量时,若想换行,使得代码更有阅读性,则可以使用反斜杠''。表示尚未结束

aaa = "te"+\
    "st888"
print(aaa)

变量操作

若是想要在变量上增加内容,则可以使用+=

a = "这是"
a += "继续"
print(a)

变量内插

f字符串(python3.6及以上版本)

要在字符串中插入变量的值,需要使用f字符串,f是format(格式设置)的意思

基本形式f"{变量}",将花括号内的变量替换为字符串

演示代码

first_name = "ada"
last_name = "lovelace"
full_name = f"{first_name} {last_name}"

#可以在f字符串中将普通字符串与变量混合,以及与方法进行同时使用
message = f"Hello, {full_name.title()}!"
print(message)

#结果为
#Hello, Ada Lovelace!

#可以不赋值,直接print
print (f"test,{full_name.title()}!")

format方法

对版本无要求

# 演示形式
# 如果中括号内无内容,则会顺序填入变量
full_name="{} {}".format(first_name,last_name)

# 可以用数字指定是哪个变量,就能完成一个变量多次输入
full_name="{0} {1} {0}".format(first_name,last_name)

# 也可以使用关键词进行绑定
full_name="{key1} {key2} {key1}".format(key1=first_name,key2=last_name)
绑定的关键词并不是变量,不会影响同名的变量

格式化

如果插入变量是浮点数,则可以在花括号内进行格式化

name = "小明"
gap = 3.1234

#f字符串
print(f"{name} 你好,您的成绩是:{gap:.2f}")
  
# format
print("{0}您好,您的成绩是:{1:.2f}".format(name,gap))

比如这里用:.2f格式化为2个小数位

方法

对变量使用方法,变量与方法之间用.连接,方法后续的括号中写方法的参数

对象.方法名(..)

亦可以对字符串直接使用方法

注意,使用方法并不会修改变量原始内容

如下代码

name ="ada lobelace"
print (name.title())
#print中将name变量使用方法title(首字母大写),此处title无需参数,所以()内为空

#输出结果
#Ada Lobelace

#类似的
print(name.upper())        #全大写
print(name.lower())        #全小写

#想要固定下来这个结果,就重新赋值
name=name.title()

#直接对字符串使用
print("lovelace".title())

删除空白

test=" a b c "

print(test)
#清除末尾空白
print(test.rstrip())
#清除开头空白
print(test.lstrip())
#清除两边的空白
print(test.strip())

列表

基本用法

吐槽:为什么不叫数组??

#定义一个列表,由中括号括住,单双引号无所谓
#没被引号括住的是数字
test = ['a','b',"c",'56',56]

#打印某一个元素,数字是索引位置,负数是反向
print(test[1])
print(test[-2])
#组合用法
print(test[1].title())
print(f"this is {test[0]}")

索引若下标越界,会直接报错

元组

元组是不可变列表的意思,即无法修改元素

定义元组通过逗号,书上代码为了整洁性会建议加上圆括号

因此,如果需要定义单元素的元组,同样也需要一个逗号

a = 200, 50
c = (50, 60)
#单元素元祖
b = 100,

虽然无法修改元素,但重新定义元组是合法的

t_a = (3, 4, 5)
t_a = 3,5,7
print(t_a)

即使元组内元素是变量,在外部修改变量也不会改变元组的元素

但是,如果是列表,则内部依然会变

列表操作

与上述变量不同,列表属于可变,使用方法会直接改变列表本身

增添改删

#直接对索引赋值即为修改该索引值
test[1]="d"
print(test)

#添加到末尾,直接使用方法append,且无需赋值操作
test.append("t")
print(test)

#插入元素,方法insert,指定位置
test.insert(1,"k")
print(test)

#删除元素
## del函数,直接删除
del test[0]
## pop方法,提取出1个元素,参数可以指定元素索引,留空则为末尾
test_p=test.pop()
print(test)
print(test_p)
test_p=test.pop(1)
## remove方法,匹配删除元素,可以由变量指定,注意若重复则只匹配一次,需要使用循环
test.remove("a")
no_c = "c"
test.remove(no_c)

排序

#sort方法,按字母顺序排序,改变列表
test.sort()
print(test)
##加参数,反向排序
test.sort(reverse=True)

#sorted方法,临时排序,不改变列表
print(sorted(test))
##同样接受反向排序的参数
print(sorted(test,reverse=True))

其他操作

#reverse方法,反转列表
test.reverse()
print(test)

#len函数,获取列表长度,长度从1开始计数
print(len(test))

for循环遍历

循环可以对列表,字符串,字典等操作

对字符串操作则是依次遍历每一个字符(不用像perl一样split后做成数组输出,很方便)

#结构
for (取出的值赋值临时变量) in (列表名) :
    ...(缩进部分代码表示循环框架内语句)
(非缩进则表示在循环外)

注意临时变量不会在循环结束后自动删除,而是继续保留为最后一次被赋值的值

#定义列表
test = ['a','b','c',"56"]
#遍历输出
for test_a in test:
    print(test_a)

列表解析(for循环单行式存储列表)

对一个列表内所有内容进行相同修改,并存储为一个新的列表,可以快捷的使用单行式for

结构为

新列表名 = [(待存储的临时变量及所需操作) for (临时变量) in (列表)]

示例代码

#对数字操作
t_a=[1,2,3]
aa = [tt+1 for tt in t_a]
print(aa)

#对字符串操作
t_b=['a','b','c',"56"]
bb = [f"{tb}test" for tb in t_b]
print(bb)

创建连续列表

使用range函数构建一个连续数字,注意不会显示大于或等于第二位参数的数,例如range(1,6),输出是1-5

for t in range(1,6):
    print(t)

可以将其固定为列表,需要函数list

te=list(range(1,3))

for tea in te:
    print(tea)

range函数支持指定步长,即间隔,由第三位参数指定

for tea in range(1,9,2):
    print(tea)

数学操作

#max与min函数,返回列表最大/最小值/和
test = list(range(1,25))
print(max(test))
print(min(test))
print(sum(test))

切片

输出部分列表(也支持字符串变量)内容,指定索引范围,注意,索引同样不能等于或大于终止索引序号

索引也允许使用负数

切片形式可以在任意地方使用,例如for循环

t = ['a', 'b', 'c', "56"]
print(t[0:2])
#起始索引可以不指定,默认从头开始
print(t[:3])
#终止索引也可以不指定,一直输出到末尾
print(t[1:])

#负数索引
print(t[-2:])	#始终输出最后2位

同样的,切片也能指定步长,由第三位参数指定

示例如下

t = ['a', 'b', 'c', "d",'f','g']
print(t[0:5:2])

列表复制

区分浅拷贝与深拷贝,是由于列表中的嵌套导致的区别

由于嵌套在列表中是以地址指向的信息存在,因此浅拷贝只能拷贝这个地址信息,而不能使其独立存在,顾名思义,修改嵌套的内容,会同时生效

非拷贝(别名)

注意这种方法并不是拷贝,修改其中一个列表,也会对另一个列表产生影响

可以认为是对旧列表起了个别名,实际都是同一个列表

t = ['a', 'b', 'c', "d",'f','g']
a = t
t.insert(2,'3')
print(t)
print(a)

浅拷贝(无法影响嵌套)

几种方法等效

copy方法

a = [1,2,[3,4]]
b = a.copy()

print("a:",a)
print("b:",b)
print("第一次改变:")
a[1] = 666
print("a:",a)
print("b:",b)
print("第二次改变:")
a[2][0] = 777
print("a:",a)
print("b:",b)

##输出
a: [1, 2, [3, 4]]
b: [1, 2, [3, 4]]
第一次改变
a: [1, 666, [3, 4]]
b: [1, 2, [3, 4]]
第二次改变
a: [1, 666, [777, 4]]
b: [1, 2, [777, 4]]

切片方式

t = ['a', 'b', 'c', "d",'f','g']
b=t[:]
print(b)

list赋值

a = [1,2,[3,4]]
b = list(a)

以及包括,列表解析,for循环

深拷贝

deepcopy函数

import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)

判断

在Python中,None、任何数值类型中的0、空字符串“”、空元组()、空列表[]、空字典{}都被当作False,还有自定义类型,如果实现了  __ nonzero __ () 或 __ len __ () 方法且方法返回 0 或False,则其实例也被当作False,其他对象均为True。

符号

#比较运算符
==	相等
!=	不等
>	大于
<	小于
>=	大于等于

#特殊
not	判断反向仅用于后续的一次运算可用括号括起来整体反向
##示例代码
a = 6
if not a > 5:
    print("goo" * 3)
else:
    print("nno")

#判断多个条件,可以多个叠加
and	两个条件满足
or	任意一个条件满足

#其他符号
in	判断元素是否在列表中
not in 判断元素是否不在列表中
##示例代码
a = ['a', 'b', 'c', 'd', 'e']
if 'c' in a:
    print("good")

and or多重混合的解释

优先级关系:

not > and > or

可以使用括号改变

基础

下面是最简单的逻辑运算: 这里 1,2 都是Ture; 0,‘’都是False

1 and 2 ==> 2 1 or 2 ==> 1

1 and 0 ==> 0 1 or 0 ==> 1

0 and 1 ==> 0 0 or 1 ==> 1

0 and '' ==> 0 0 or '' ==> ''

总结:

or 从左到右,返回第一个为真的值,都为假返回后一个值

and 从左到右,若所有值均为真,则返回后一个值,有一个假的值,则返回第一个假的值

混合形式-短路逻辑

不推荐混合写法,复杂难懂,也不利于后续维护

逻辑运算符 and / or 一旦不止一个,其运算规则的核心思想就是短路逻辑。好的,那我们就来了解一下短路思想:

表达式从左至右运算,若 or 的左侧逻辑值为 True ,则短路 or 后所有的表达式(不管是 and 还是 or),直接输出 or 左侧表达式 。

表达式从左至右运算,若 and 的左侧逻辑值为 False ,则短路其后所有 and 表达式,直到有 or 出现,输出 and 左侧表达式到 or 的左侧,参与接下来的逻辑运算。

若 or 的左侧为 False ,或者 and 的左侧为 True 则不能使用短路逻辑

if形式

#布尔式
if [条件]:
    ...(执行代码)
##示例
a = True
if a:
    print("good")

#条件式(本质是一样的,条件式解出布尔值交给if判断)
if (待判断对象) (判断符) '(判断值)':
    (缩进)...(执行代码)
  
##示例
a = ['a', 'b', 'c', 'd', 'e']
for aa in a:
    if aa == 'c':
        print(aa.title())

与perl不同,不能直接对未定义变量判断

在python中,可用多种方法,其一是使用dir()获取定义变量列表,然后使用if判断

注意,是以字符串(变量名)形式判断,不能直接使用变量

print(dir())
if 'b' in dir():
    print("good")

if-else

else语句为判断失败后执行

if 'b' in dir():
    print("good")
else:
    print("这个变量未定义")

if-elif-if

检查多种形式,对应不同情况,elif可以无限叠加

基本形式

b = 4
if 'b' not in dir():
    print("这个变量未定义")
elif b < 5:
    print("b小于5")
else:
    print("b是其他值")

为了使判断更为安全,最后的else可以省略,以使判断不会出现意外情况

match-case(>3.10)

类似c语言的switch-case语句,无需反复if,else,根据不同的值执行对应的代码块

match 后的对象会依次与 case 后的内容进行匹配,如果匹配成功,则执行匹配到的表达式,否则直接跳过,_ 可以匹配一切,亦即是c语言的default

匹配内容较为复杂,见后续,这里仅描述判断语句

示例如下

b = 4
match b:
    case 5:
        print("b等于5")
    case 3|4:
        print("b是3或4")
    case _:
        print("b未知")

使用|符号可以一次性匹配多种结果

集合

概念

集合的概念是一个无序不重复元素集,即使在创建时有重复,最终存储的也是无重复的

创建集合的方法,是用花括号包裹

可以理解为无重复列表,区别是输出的时候顺序是随机的

aa = {'a','b','c','a'}
print(aa)

可以使用set函数来转换为集合,自动进行去重处理

集合操作

添加元素

set 集合中添加元素,可以使用 set 类型提供的 add() 方法实现,该方法的语法格式为:

setname.add(element)

其中,setname 表示要添加元素的集合,element 表示要添加的元素内容。

需要注意的是,使用 add() 方法添加的元素,只能是数字、字符串、元组或者布尔类型(True 和 False)值,不能添加列表、字典、集合这类可变的数据,否则 Python 解释器会报 TypeError 错误。例如:

a = {1,2,3}
a.add((1,2))
print(a)		# {(1, 2), 1, 2, 3}

a.add([1,2])	# 报错
print(a)

删除元素

删除现有 set 集合中的指定元素,可以使用 remove() 方法,该方法的语法格式如下:

setname.remove(element)

使用此方法删除集合中元素,需要注意的是,如果被删除元素本就不包含在集合中,则此方法会抛出 KeyError 错误,例如:

a = {1,2,3}
a.remove(1)
print(a)		#{2, 3}

a.remove(1)		#报错
print(a)

上面程序中,由于集合中的元素 1 已被删除,因此当再次尝试使用 remove() 方法删除时,会引发 KeyError 错误。

如果我们不想在删除失败时令解释器提示 KeyError 错误,还可以使用 discard() 方法,此方法和 remove() 方法的用法完全相同,唯一的区别就是,当删除集合中元素失败时,此方法不会抛出任何错误。

a = {1,2,3}
a.remove(1)
print(a)	#{2, 3}

a.discard(1)
print(a)	#{2, 3}

集合运算

集合最常做的操作就是进行交集、并集、差集以及对称差集运算

img

上图中,有 2 个集合,分别为 set1={1,2,3} 和 set2={3,4,5},它们既有相同的元素,也有不同的元素。以这两个集合为例,分别做不同运算的结果如表 1 所示。

运算操作 Python运算符 含义 例子
交集 & 取两集合公共的元素 >>> set1 & set2 {3}
并集 | 取两集合全部的元素 >>> set1 | set2 {1,2,3,4,5}
差集 - 取一个集合中另一集合没有的元素 >>> set1 - set2 {1,2} >>> set2 - set1 {4,5}
对称差集 ^ 取集合 A 和 B 中不属于 A&B 的元素 >>> set1 ^ set2 {1,2,4,5}

字典

即perl语言中的哈希

字典是一系列的键值对,键与值一一对应

键必须是不可变数据类型,如字符串,数值,元组,等

元组可以实现多个属性描述一个值,比如张三,53岁

可以做更加精确的指向

值可以是任意,比如数,字符串, 列表,或者也可以是字典

与perl不同的是,使用for循环遍历,存储于字典中的键顺序不会变

可以理解字典为存储一系列的变量的列表

定义字典

用花括号包裹,引号包裹内容,单双引号均可,键值对使用冒号对应,不同键值对之间是逗号

输出内容则使用中括号,内部用引号包裹的任意一个键内容即可

注意与集合的区别,如果花括号内没有键值对,则被认为是集合

alias_0 = {'color':'red','point':'5'}
print(alias_0['color'])

# 遍历输出
for aa in alias_0:
    print(aa + "\t" + alias_0[aa])

可以换行,注意缩进

user_0 = {
    'username': 'efermi',
    'first': 'enrico',
    'last': 'fermi',
}

print(user_0)

输出不存在的键会直接报错,可以使用方法get,使得不存在值时返回一个默认值

第一个参数是键,第二个参数是默认返回值,如果未指定第二个参数,则会默认返回None,意指空值

user_0 = {
    'username': 'efermi',
    'first': 'enrico',
    'last': 'fermi',
}

print(user_0.get("2", "没有这个值"))

键值对操作

获取键值对数量的方法,可用len函数

user_0 = {
    'username': 'efermi',
    'first': 'enrico',
    'last': 'fermi',
}

print(len(user_0))

添加

类似数组,直接定义一个键等于值即可,但必须已经先存在字典(可以创建一个空字典)

alias_0 = {}
alias_0["bb"] = 3

注意,如果已经定义了同名列表,则不能作为字典添加键值对

不同的是,数字下标可以不加引号即可添加

如果已经定义了字典,那么做类似操作列表索引的操作是被视作添加键值对

alias_0 = {"color": "red", "point": "5"}
print(alias_0)

alias_0["bb"] = 3
print(alias_0)

alias_0[2] = 6
print(alias_0)

修改

如同添加键值对一样,对一个键赋值,即可修改

若要检查键是否存在,可以使用in进行检查,这个表达式返回的值是布尔值

user_0 = {
    'username': 'efermi',
    'first': 'enrico',
    'last': 'fermi',
}

print("last" in user_0)

示例(书上源码)

# 定义一个物体的属性,根据速度决定移动距离
alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print(f"Original position: {alien_0['x_position']}")

# 检查速度决定移动距离
if alien_0['speed'] == 'slow':
    x_increment = 1
elif alien_0['speed'] == 'medium':
    x_increment = 2
else:
    x_increment = 3

# 新位置是旧位置加移动距离
alien_0['x_position'] = alien_0['x_position'] + x_increment

print(f"New position: {alien_0['x_position']}")

删除

同列表一样,使用del语句

alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print(alien_0)

del alien_0["speed"]
print(alien_0)

遍历

基本

a = {
    "age": 4,
    "year": "2022",
    "name": "ge"
}

for key, value in a.items():
    # 注意必须使用f函数输出,因为“+”只能用于字符串的连接
    # 而字典的键值都有可能是别的数值类型
    print(f"键:{key}")
    print(f"值:{value}")

方法items返回字典的键值对的一个元组

与perl不同的是,如果for循环中只赋值给一个值,那么输出的并不只是键,而是包含单独这个键与值的元组

for b in a.items():
    print(b[0])
    print(f"{b[1]}\n")

单独键或值

方法keys可以只返回字典中的键

for k in a.keys():
    print("键:"+ k)

for循环字典时默认输出的就是键

因此可以省略这个方法

for k in a:
    print("键:"+ k)

这个方法实际上是返回了包含整个字典的键的列表,所以可以用来检查某个键是否在字典中

if "k" not in a.keys():
    print("不存在")

方法values可以只返回字典中的值

for b in a.values():
    print(f"这是{b}")

如果值发生重复,那么会输出许多无意义的重复

如果要剔除重复,筛选出非重复项的值,则可用set函数,创建一个集合

a = {
    "age": "4",
    "year": "2022",
    "name": "ge",
    "aaa":"ge"
}

for b in set(a.values()):
    print(f"这是{b}")

遍历顺序

因为keys返回的是一个列表,因此同样可以使用列表的方式进行排序后输出,比如sorted函数

a = {
    "age": "4",
    "year": "2022",
    "name": "ge"
}

for b in sorted(a.keys()):
    print(f"这是{b}")

嵌套

字典存储在列表中

基本形式

alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}

aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
    print(alien)

可以以匿名形式

aliens = []

for alien_number in range(30):
    new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
    aliens.append(new_alien)

for alien in aliens[:5]:
    print(alien)

print(f"Total number of aliens: {len(aliens)}")

修改匿名的嵌套字典,则可以用循环赋值

for alien in aliens[:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10

for alien in aliens[:5]:
    print(alien)

列表存在字典中

pizza = {
    'crust': 'thick',
    'toppings': ['mushrooms', 'extra cheese'],
	}

print(pizza['toppings'][1])

多维字典 - 字典存在字典中

users = {
    'aeinstein': {
        'first': 'albert',
        'last': 'einstein',
        'location': 'princeton',
    },
    'mcurie': {
        'first': 'marie',
        'last': 'curie',
        'location': 'paris',
    },
}

print(users["mcurie"]["last"])

输入

函数input

input之后,这个变量就会被输入的内容所替代(只是作为一个提示信息存在)

message = input("请输入并按回车键确认: ")
print(message)

# 被替换了
print(message)

注意input输入的是字符串,若要对输入的数值进行计算,则需要使用int进行转换

age = input("How old are you? ")
age = int(age)

# 这里其实可以省略写法
age = int(input("How old are you? "))

if age >= 18:
    print("good")

多行形式

message = "请输入内容,"
message += "\n并按回车键确认: "
message = input(message)
print(message)

循环

for循环

见列表中的小节,for循环遍历

适用于有明确循环次数时使用

while循环

适用于在==没有==明确循环次数时使用

基本形式

满足条件时退出循环

while 条件A:
    行动B
image-20230212214451529

示例

current_number = 1
while current_number <= 5:
    print(current_number)
    current_number += 1

循环输入

prompt = "输入一些东西,我将重复你的话:"
prompt += "\n输入 'quit' 退出. \n"

# 必须先定义,否则无法判断不存在的变量
message = ""

while message != 'quit':
    message = input(prompt)

    if message != 'quit':
        print(message + "\n")

结束循环的方式

这是接下来代码的前面部分

prompt = "输入一些东西,我将重复你的话:"
prompt += "\n输入 'quit' 退出. \n"
message = ""

使用标志来简化循环判断

可以使一个标志来代表所有的判断条件,否则while的条件会很复杂

...

active = True
while active:
    message = input(prompt)
    if message == 'quit':
        active = False
    else:
        print(message +"\n")

退出当次循环 - continue语句

执行之后,后面的语句不再执行,而是直接进入下一循环

# 这个示例只会输出不能被2整除的数(奇数)
current_number = 0
while current_number < 10:
    current_number += 1
    if current_number % 2 == 0:
        continue
    print(current_number)

退出整个循环 - break语句

立即退出循环,适用于所有循环,只能跳出一层循环

...

while True:		# True就是这个循环条件永远成立
    message = input(prompt)
    if message == 'quit':
        break
    else:
        print(message+"\n")

使用while处理列表和字典

列表

有内容的列表是Ture,空列表是False

示例

# 将一个列表中的数据经过验证后逐个转移到另一个列表
unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []

while unconfirmed_users:
    current_user = unconfirmed_users.pop()
    print(f"验证用户: {current_user.title()}")
    confirmed_users.append(current_user)
  
print("\n以下用户已确认:")
for confirmed_user in confirmed_users:
    print(confirmed_user.title())

删除列表中存在的所有指定值(remove只能删除一次)

pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat']
print(pets)

while 'cat' in pets:
    pets.remove('cat')

print(pets)

字典

示例

responses = {}

while True:
    name = input("你的名字是?\n")
    question = input("你喜欢的语言是什么?\n")
    responses[name] = question

    repeat = input("还有人接受调查吗?输入'no'退出\n")
    if repeat == "no":
        break

print("调查结束\n")
for name , response in responses.items():
    print(f"{name}喜欢的语言是{response}")

函数

基本结构

很明显,这是C语言的函数概念,类似perl中的子程序(不同的是,函数必须写在调用之前)

自定义一个函数,用于代码的反复执行,特点是固定的输入则有着固定的输出

函数应该保持一种理念,即每一个函数只负责一项具体工作

一个示例

def greet_user():
    # 函数内容
    print("Hello!")

greet_user()

第一行解析:

  • def 表示定义函数(与perl不同,函数名必须小写)
  • greet_user是函数名,后面的括号是接受参数的部分,空则代表无需任何参数即可执行,后续再看
  • :结尾

这个示例函数无需任何参数,一旦调用就会打印Hello!

变量的作用域

全局变量

在函数外定义的变量就是全局变量,在函数中可以被直接读取

a = 5  # 全局变量
print(id(a))

def func():
	print(a)
	print(id(a))
'''
94648897326528
5
94648897326528
'''

id() 函数返回对象的唯一标识符,标识符是一个整数。

实际上是对象的内存地址

局部变量

在函数中,可以使用与全局变量相同的变量名,默认为局部变量

局部变量被改变不会影响同名全局变量的值

a = 5  # 全局变量

def func():
	a=5
	a=a+1  # 6
	print(a)

func()
print(a)
'''
6
5
'''

在函数中修改全局变量

因此,为了避免混淆,在函数中不能直接修改全局变量的值,必须使用global语句标明其为全局变量

a = 5  # 全局变量

def func():
	global a
	a=a+1  # 6

func()
print(a)
'''
6
'''

不能使一个变量名在函数中又当局部变量又是全局变量

传入参数

基本形式

def greet_user(username):
    print(f"Hello, {username.title()}!")
  
greet_user('jesse')

这个函数拥有一个变量接收参数信息,写在括号中即可

实参与形参

在定义函数的括号中,接收参数的变量被称为 形参

与之对应的,在调用函数时,写在函数参数括号中的变量被称为 实参

代码规范提示:

如果一次性使用了多个形参,使得一行特别长,则在左括号打完之后,回车,并前置按两个tab键

IDE会帮你操作,但自己注意,如下所示

def function_name(
        parameter_0, parameter_1, parameter_2,
        parameter_3, parameter_4, parameter_5):

参数调用方式

位置实参

按照传入实参的顺序,依次放入形参中

例如:

def describe_pet(animal_type, pet_name):
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')

关键字实参

将形参作为关键词使用,将实参与关键词绑定,无需考虑顺序

例如

def describe_pet(animal_type, pet_name):
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet(animal_type='hamster', pet_name='harry')

参数默认值

形参可以设置默认值,如在未接受实参的传入时使用默认值

默认值必须绑定关键词

def describe_pet(animal_type='dog'):
    print(f"\nI have a {animal_type}.")


describe_pet(animal_type='mouse')
describe_pet()

上述代码,若不传入animal_type,则默认为dog

可以使得默认值为空,让这个参数变为可选项,如下所示

def get_formatted_name(first_name, last_name, middle_name=''):
    if middle_name:
        full_name = f"{first_name} {middle_name} {last_name}"
    else:
        full_name = f"{first_name} {last_name}"
    print(full_name)

get_formatted_name('jimi', 'hendrix')
get_formatted_name('john', 'hooker', 'lee')

总结 - 混合调用

上述三种参数调用形式可以混合使用

例如

def tes (test1, test2, tt="默认", gg="g"):
    print(f"这是测试{test1},这是{tt},这是测试{test2},这是g{gg}")


tes("1", test2="22", gg="3")
tes("1", "22", , gg="3")

规则如下

  • 默认形参(函数中接受传入参数的变量)后面不允许出现非默认形参,所以必须将默认形参全部放在后面
  • 位置实参(函数调用时的参数)必须在所有绑定了关键词实参的前面
  • 默认形参同样接收位置实参的传入

虽然怎么样都可以,但不要写的太复杂

返回值

就是没有直接输出的函数,有助于代码模块化

与perl不同,默认返回为None,空值,因此必须使用return语句指定函数的返回值

返回一个字符串

def get_formatted_name(first_name, last_name):
    full_name = f"{first_name} {last_name}"
    return full_name.title()

musician = get_formatted_name('jimi', 'hendrix')
print(musician)

返回一个字典

def build_person(first_name, last_name):
    person = {'first': first_name, 'last': last_name}
    return person

musician = build_person('jimi', 'hendrix')
print(musician["first"])
def build_person(first_name, last_name, age=None):
    person = {'first': first_name, 'last': last_name}
    if age:
        person['age'] = age
    return person

musician = build_person('jimi', 'hendrix', age=27)
print(musician)

传递列表

基本示例

def greet_users(names):
    for name in names:
        msg = f"Hello, {name.title()}!"
        print(msg)

usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)

列表的变与不变

在函数中,对列表的修改是永久的

def print_models(unprinted_designs, completed_models):
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        print(f"Printing model: {current_design}")
        completed_models.append(current_design)


def show_completed_models(completed_models):
    print("\nThe following models have been printed:")
    for completed_model in completed_models:
        print(completed_model)


unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_models = []

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
show_completed_models(unprinted_designs)

可以让实参是列表的切片形式,这样就不会改动列表了

比如

function_name(list_name[:])

上面的列表想保留则如下

print_models(unprinted_designs[:], completed_models)

变长参数

核心思想与perl相同,将参数收入一个数组中

在python中的实现和形式略有不同,是将其收入元组中,且参数需要用*星号标记

def make_pizza(*toppings):
    print(toppings)
    for topping in toppings:
        print(f"- {topping}")


make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

注意,这同样需要作为形参位置的规则,收入任意数量的形参必须在位置形参和关键字形参之后

def make_pizza(size, *toppings):
    print(f"\nMaking a {size}-inch pizza with the following toppings")
    for topping in toppings:
        print(f"- {topping}")

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

特别的,python可以接收字典的键值对

由于接受参数的形参需要特别标记,同理,若想将其收入字典中,则需要两颗星标记形参**,表明为字典

示例

def build_profile(first, last, **user_info):
    user_info['first_name'] = first
    user_info['last_name'] = last
    return user_info

user_profile = build_profile('albert', 'einstein',
                             location='princeton',	# 直接传入键值对,存入user_info
                             field='physics')
print(user_profile)

模块

写好的函数可以放在模块中(独立的文件),只有在导入时调用,使得代码更加简洁清晰,易于分享

模块文件的扩展名为py

创建/导入模块

基本示例

调用模块的基本命令,import 模块名

将函数放入模块中调用,如下所示

  1. 模块文件,文件名pizza.py
def make_pizza(size, *toppings):
    """概述要制作的比萨。"""
    print(f"\nMaking a {size}-inch pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")
  1. 主程序
import pizza
pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

Python读取这个文件时,代码行import pizza 让Python打开文件pizza.py,并将其中的所有函数都复制到这个程序中

要调用被导入模块中的函数,可指定被导入模块的名称 pizza 和函数名 make_pizza() ,并用句点分隔

指定导入特定函数

语法 - from (模块名) improt (函数名),函数名可以有多个,用逗号分割

例如基本示例中的模块

from pizza import make_pizza
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

使用这种方式导入的函数,无须使用句点语句,函数名是显式的,因此使用也可以直接用

可以一次性导入全部函数,使用*号,注意这种用法是有危险的,特别是你不清楚的别人的模块,因为会覆盖已有程序的函数或变量

from pizza import *

函数别名

考虑到导入的函数可能与程序中发生冲突,或太长,可指定别名,使用as关键字

语法 - from (模块名) improt (函数名) as (函数别名)

例如

from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')

模块别名

as也可以给模块指定别名

语法 - import (模块名) as (模块别名)

示例

import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

   
  • 摸鱼周报

    每周五的摸鱼派活动-摸鱼周报 发表你的每周总结

    289 引用