【Python】绪论

目录

1 顺序结构

1.1 常量

约定俗成地,常量命名全部大写。

PI = 3.1415926

1.2 输入

x = input("Please input a number:")

这时x是一个字符串(str),若要获得一个数字,则需要int()。

x1 = int(x)

1.3 条件语句

注意冒号和严格的缩进

money = int(input("Please input your money:"))

if money > 5000:
    print("Buy a card.")
elif money > 1000:
    print("Just wash your feet.")
else:
    print("Just go ahead.")

1.4 for循环

可以迭代字符串或者range,以下范围都不包含n

1.4.1 range(n)

表示从0到n。

1.4.2 range(m, n)

表示从m到n。

1.4.3 range(m, n, step)

表示从m到n,且步长为step。

1.5 代码占位

if a > 100:
    pass

2 数据类型

2.1 基础数据类型

2.1.1 整数int

a = 10

2.1.2 浮点数float

a = 10.5

2.1.3 布尔类型bool

a = bool('1')  # a == True
b = bool('')   # b == False
c = bool(-1)   # c == True
d = bool(0)    # d == False

2.2 字符串string

2.2.1 长度

使用 len 函数。

s = "Hello world!"
print(len(s)) # 12

2.2.2 字符串格式化

可以使用%d(整数)、%s(字符串)、%f(浮点数)来占位。

name = kid
age = 10

s1 = "I am %s, I'm %d years old." % (name, age)
s2 = "I am {}, I'm {} years old.".format(name, age)
s3 = f"I am {name}, I'm {age} years old."

2.2.3 索引和切片

用索引的方式提取某个字符。

s = "I am Li Hua."
print(s[-1]) # -:reverse

切片提取字符时,前闭后开

s = "I am Li Hua."
print(s[5:11]) # Li Hua
print(s[8:]) # Hua.
print(s[:4]) # I am
print(s[-2:-8:-1]) # auH iL

2.2.4 大小写切换

首字母大写使用 capitalize 函数。

s = "python"
s1 = s.capitalize()
print(s1) # Python

全部英文单词首字母大写使用 title 函数。

s = "I have a dream!"
s1 = s.title()
print(s1) # I Have A Dream!

全部变成小写使用 lower 函数。

s = "I Have A Dream!"
s1 = s.lower()
print(s1) # i have a dream!

全部变成大写使用 upper 函数,值得注意的是, lower 函数不支持部分希腊字母,但是 upper 函数支持,所以 upper 函数的使用频率更高。

s = "I Have A Dream!"
s1 = s.upper()
print(s1) # I HAVE A DREAM!

比如网页验证码不区分大小写,就可以使用此函数。

verify_code = "xAd1"
user_input = input("Please input the verify code:")

if verify_code.upper() == user_input.upper()
    print("Right!")
else
    print("Wrong!")

2.2.5 切割和替换

去除字符串两端的空格、制表符或换行符可以使用 strip 函数。

s = "   I Have A Dream!          "
s1 = s.strip()
print(s1) # I Have A Dream!

替换可以用 replace 函数,格式是 replace(str1, str2[, max]) 。其中如果指定max,则表示替换的最多次数。如果要去掉所有str1,则str2等于空字符串。

s = "   I Have A Dream!          "
s1 = s.replace(" ", "")
print(s1) # IHaveADream!

字符串切割使用 split 函数,且会返回一个列表。

s = "python_java_c_c#_javascript"
lst = s.split("_")
print(lst) # lst is a list, composed of strings.

2.2.6 查找与判断

查找可以使用 find 函数,并返回所找内容的位置。若查找不到,则返回 -1

s = "Hello world!"
ret1 = s.find("world")
ret2 = s.find("word")
print(ret1) # 6
print(ret2) # -1

查找还可以使用 index 函数,但是与 find 函数不同的是,当未查找到时,程序报错。
如果要判断一个子串是否存在于一个字符串,则可以使用 innot in

s = "Hello world!"
print("word" in s) # False
print("world" in s) # True
print("word" not in s) # True

如果要判断字符串是否以某一字符开始,可以使用 startswith 函数。

s = "Hello world!"
print(s.startswith("H")) # True
print(s.startswith("h")) # False

判断是否为整数,使用 isdigit 函数。

s = "114514"
print(s.isdigit()) # True

2.2.7 字符串的连接

将列表内的字符串连接为一个字符串,使用 join 函数。

lst = ["python", "c", "c#", "javascript"]
s = "_".join(lst)
print(s) # python_c_c#_javascript

2.3 列表list

在python中用中括号([])来表示一个列表,其中元素用逗号(,)隔开。

2.3.1 特性

列表的元素可以是任意数据类型。像字符串一样,列表也可以进行索引和切片操作。但值得注意的是,如果索引超过范围就会报错。可以用for循环一项一项遍历。可以使用 len 来求出列表的长度。

2.3.2 增删改查

增添内容使用 append 函数,将放在列表的最后。

lst = []
lst.append("python")
lst.append("c")
lst.append("java")
print(lst) # ['python', 'c', 'java']

插入内容使用 insert 函数,可以指定插入的位置。

lst = ["python", "c", "javascript"]
lst.insert(2, "c#")
print(lst) # ['python', 'c', 'c#', 'javascript']

合并两个列表使用 extend 函数。

lst = ["python", "c", "javascript"]
lst.extend(["c#", "java"])
print(lst) # ['python', 'c', 'javascript', 'c#', 'java']

删除可以使用 pop 函数,需要给出索引,会返回删除的元素。

lst = ["python", "c", "javascript"]
ret = lst.pop(2)
print(lst) # ['python', 'c']
print(ret) # javascript

删除也可以使用 remove 函数,此时直接给出元素即可,若同时存在多个相同的给出元素,则删除第一个。值得注意的是,使用remove后,列表后方所有项都会向前移动一位,此时若循环遍历,则会有部分元素被忽略。

lst = ["python", "c", "javascript"]
lst.remove("c")
print(lst) # ['python', 'javascript']

2.3.3 排序

使用 sort 函数。若在加上 reverse=True ,则表示降序排序。

lst = [9, 3, 7, 5, 1]
lst.sort()
print(lst) # [1, 3, 5, 7, 9]
lst.sort(reverse=True)
print(lst) # [9, 7, 5, 3, 1]

2.3.4 列表嵌套

lst = [[1, 3, 2], 'world', ['hello', [1, 3], 'histology']]
print(lst[2][1][1]) # 3

2.3.5 解构(解包)

列表和元组两种数据类型都可以进行此操作。需要注意的是,前面的元素个数一定要与列表的元素个数相同,否则报错。

lst = [3, 2]
a, b = lst
print(a) # 3
print(b) # 2

2.4 元组tuple

相当于不可变的列表,使用小括号表示(())。若尝试修改,则会报错。当元组只有一个元素时,定义时需要多加一个逗号,否则括号将被视为优先级。

t1 = ("haha", )
t2 = ("haha")
print(t1) # ('haha')
print(t2) # 'haha'

2.5 集合set

乱序地存放一堆元素,用花括号({})表示。元素必须是可以哈希的值,即不能存储列表、字典和集合。

2.5.1 创建空集合

不能直接使用一堆花括号,那会创建一个字典,但是可以用 set()

s = set()

2.5.2 增加、删除元素

s = set()
s.add('python')
s.add('c')
s.remove('python')
print(s) # ('c')

2.5.3 集合的运算

取交集可以用 &intersection 函数。取并集可以用 |union 函数。取差集可以用减号(–)。

s1 = {"python", "java"}
s2 = {"python", "c#"}
print(s1 & s2) # {'python'}
print(s1 | s2) # {'python', 'java', 'c#'}
print(s1 – s2) # {'java'}

集合可以用于去除重复,但是结果是无序的。

lst = [1, 3, 3, 7, 1, 5]
print(list(set(lst))) # [1, 7, 5, 3]

2.6 字典

以键值对的形式存放,以花括号({key: value})表示。其中,key必须可哈希,但是value可以是任何值。

2.6.1 增删改查

设置默认值可以用 setdefault 函数,若字典中已经有给定的key,则赋值,否则创建新值。

dic = dict()
dic['jay'] = "chou"
dic.setdefault['jay', "kunling"]
dic.setdefault['tom', "soup"]
print(dic['jay']) # chou
print(dic['tom']) # soup

删除值可以使用 pop 函数,或 del 函数。pop函数需要给出key值。

dic = {'jay': "chou", 'tom': "soup"}
dic.pop['jay']
del dic['jay'] # not quite often used.

查询字典值可以直接索引,也可以用 get 函数。但是值得注意的是,key不存在时,用索引则程序报错,用get函数则返回None。

dic = {'jay': "chou", 'tom': "soup"}
print(dic['jay001']) # Error!
print(dic.get('jay001')) # None

2.6.2 循环和嵌套

可以直接用for循环,直接拿到key。

dic = {'a': 1, 'b': 2, 'c': 3}
for key in dic
print(key) # a b c

如果要一次性获取所有key或者value,可以使用 keysvalues 函数。

dic = {'a': 1, 'b': 2, 'c': 3}
print(list(dic.keys()))
print(list(dic.values()))

如果要直接拿到字典的所有key和value ,则可以使用 items 函数。

dic = {'a': 1, 'b': 2, 'c': 3}
print(dic.items) # [('a', 1), ('b', 2), ('c', 3)]

当然,这个结果以元组的形式呈现,非常臃肿,因此可以考虑 拆包 的形式直接获取key和value的值。

dic = {'a': 1, 'b': 2, 'c': 3}
for k, v in dic.items():
    print(k, v)
# a 1
# b 2
# c 3

嵌套的形式与列表相同,直接使用多个中括号([])即可。

2.6.3 循环删除

与列表相同,字典在循环中删除某项,也会导致字典大小发生改变,从而报错。因此需要临时建立一个新列表,储存需要删除的key。

dic = {'a': 1, 'b': 2, 'c': 3, 'aa': 4}

temp=[]
for key in dic
    if key.startswith("a")
        temp.append(key)
for t in temp
    dic.pop(t)

print(dic) # {'b': 2, 'c': 3}

2.7 字节bytes

使用GBK、utf等字符集编码,形式是 b’code’ ,其中单引号内的内容就是编码。
使用 encodedecode 函数进行编码和解码。

s = "周杰伦"
print(s.encode("gbk"))
# b'\xd6\xdc\xbd\xdc\xc2\xd7'

print(s.encode("utf-8"))
# b'\xe5\x91\xa8\xe6\x9d\xb0\xe4\xbc\xa6'

解码后再编码可以实现两种编码的转换。

bs1 = b'\xd6\xdc\xbd\xdc\xc2\xd7'
s = bs.decode
bs2 = s.encode

2.8 运算符

2.8.1 算数运算

求余数使用百分号(%),只计算整数的除法用(//)。

2.8.2 比较运算

不等于是(!=)。

2.8.3 赋值运算

可以使用+=、-=、*=、/=来运算。

a, b = 1, 1
a = a + 1
b += 1 # equivalent.

2.8.4 逻辑运算

并且 and 、或者 or 、否定 not
优先顺序:括号> not > and > or。

2.8.5 成员运算

使用 in

2.9 文件操作

2.9.1 读取文件

语法为 open(“path”, mode=“”, encoding=“”) 。其中路径分为绝对路径和相对路径。使用相对路径时,使用两个句点(…/)表示上一级目录。而读取文件的模式mode为r(read)。使用 read 函数可以将文件的所有内容全部读取。

f = open("../resource.txt", mode="r",encoding="utf-8")

content = f.read()
print(content)

使用 readline 函数可以读取一行,且包括换行符,再使用readline函数时,将会读取下一行。由于包括了换行符,所以读取的时候可以先使用 strip 函数将多余的换行符去除。这个函数最常用,因为它不会将文件一次性全部打开,避免内存溢出。

f = open("input.txt", mode="r", encoding="utf-8")

line = f.readline().strip()
print(line)

如果要将所有内容读取并且储存到一个列表中,则使用 readlines 函数。

f = open("input.txt", mode="r", encoding="utf-8")

lines = f.readlines()
print(lines) # a list made up of string.

最关键的读取方式为直接for循环遍历文件的所有行。

f = open("input.txt", mode="r", encoding="utf-8")

for line in f: # read every line in the file.
     print(line)

2.9.2 写入文件

写入文件的模式为“w”(write),若写入的文件不存在,则会创建一个文件。每次open都会清空文件中的内容。写入文件的函数是 write 函数,且此函数输入后需要自行添加换行符。最好在进行文件操作后关闭文件,使用 close 函数。

f = open("output", mode="w", encoding="utf-8")
f.write("Hello world!")
f.close()

追加写入文件的模式为 “a”(append)。此模式下,open操作不会清空文件。

2.9.3 使用with来打开文件

with (上下文)的条件下,可以省略使用close来关闭函数,故此方法最常用。

with open("output.txt", mode="w", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

2.9.4 非文本文件

非文本文件的操作时,模式mode需要加上“b”,写为“rb”“wb”等。可以用此完成文件复制。

with open("picture1.jpg", mode="rb") as f1, \
     open("../picture2.jpg", mode="wb") as f2:
    for line in f1:
        f2.write(line)

2.9.5 修改文件

无法对一个文件同时进行读取和写入,因此需要创建一个副本,写入完成后再将副本覆盖原文件。此时需要引入 os 库,调用其中的 removerename 函数用于删除和重命名。

import os

with open("input.txt", mode="r", encoding="utf-8") as f1, \
     open("input_copy.txt", mode="w", encoding="utf-8") as f2:
    for line in f1:
        line = line.strip()
        if line.startswith("a"):
            line = line.replace("a", "b")
    f2.write(line)
    f2.write("\n")

os.remove("input.txt")
os.rename("input_copy.txt", "input.txt")

3 函数

3.1 参数

3.1.1 实参

实参用三种传递方式:位置参数关键字参数混合参数。其中混合参数中需要先输入位置参数,再输入关键字参数。

def info(name, age, hobby):
    pass

info("Octo", 18, "Sleep")
info(age=18, name="Octo", hobby="Sleep")
info("Octo", hobby="Sleep", age=18) # the three are equivalent.

3.1.2 形参

在设置时,可以设置一个默认值,如果实参不传递信息,则默认值生效。值得注意点是,若默认值参数和位置参数同时存在,则需要将默认值参数放后面(顺序:位置 > 默认值)。

def info(name, age, hobby="Sleep"):
    pass

info("Octo", 18, "Sleep")
info(age=18, name="Octo")
info("Octo", hobby="Sleep", age=18) # the three are equivalent.

如果要同时传入多个参数,且不确定参数的个数,可以使用动态传参,用星号(*)表示,形式为 *args。值得注意的是,星号接收到的值被存放在元组内。

def eat(*food):
    print(food)

eat("rice", "noodles")
# ('rice', 'noodles')
eat("rice")
# ('rice')
eat("noodles", "soup", "fruit")
# ('noodles', 'soup', 'fruit')

除此之外,动态传参还可以表示为 **kwargs ,这时这种传参是关键字传参,以字典形式储存。

def eat(**food):
    print(food)
eat(main="rice", dessert="salad", soup="fotiaoqiang")
# {'main':'rice', 'dessert':'salad', 'soup':'fotiaoqiang'}

综合考虑四种传参,为了避免数据被错误传递,应该有这样的顺序:

位置 > *args > 默认值 > **kwargs

def func(*args, **kwargs):
    print(args, kwargs)

func() # () {}
func(1) # (1, ) {}
func(1, 2, 3, 4, a=2) # (1, 2, 3, 4) {'a':2}
func(1, 2, 3, c=4, d=6) # (1, 2, 3) {'c':4, 'd':6}

如果星号(*)在实参位置,则可以将列表打散成位置参数进行传递。如果双星号(**)在实参,则可以把字典转化为关键字参数进行传递。

def func(*args):
    print(args)

stu_lst = ['a', 'b', 'c', 'd']
func(*stu_lst)
# ('a', 'b', 'c', 'd')

3.2 返回值

返回值如果未声明,则为 None 。如果写了return但是并未在之后加任何值,则同样返回None,但是函数会立即停止,而不执行之后的代码。如果返回值有多个,则以元组的形式返回。

3.3 内置函数

即python已经写好,能直接使用的函数。

3.3.1 进制转化 bin、oct、hex

binocthex 分别是2、8、16进制转化。int可以将其他进制数变为十进制。

a = 0b10010
print(int(a)) # 18

3.3.2 与数字相关 sum、max、min

summaxmin 分别是求和、最大值、最小值。

3.3.3 字符串 format

格式化使用 format ,进制转化时需要调整第二个参数内的字母。

字母进制
b2
o8
x16

如果需要补齐指定n位数,则在字母前加上 0n

a = 18
print(format(a, "08b")) # 00010010

3.3.3 Unicode码位

要寻找字符的码位,则使用 ord 函数。

a = "中"
print(ord(a)) # 20013

将码位转化为字符,则使用 chr 函数。

print(chr(20013)) # 中

3.3.4 相关内置函数

3.3.4.1 all、any

all 函数相当于and,any 函数相当于or。

lst = [0, "cook", '']
print(all(lst)) # False
print(any(lst)) # True
3.3.4.2 获取列表索引和内容 enumerate

enumerate 函数可以取得列表的索引和内容,并以元组形式返回。

lst = ["rice", "noodle", "fruit"]

for item in enumerate(lst):
    print(item)
# (0, 'rice')
# (1, 'noodle')
# (2, 'fruit')

for index, item in enumerate(lst):
    print(index, item)
# 0 rice
# 1 noodle
# 2 fruit
3.3.4.3 串联不同列表 zip

可将不同列表的信息串联起来,并以迭代器的形式储存,且迭代器的每一项是一个元组。

name = ["KeLi", "WenDi", "FuFu"]
age = [5, 2000, 3000]
hobby = ["Bomb", "Beer", "Drama"]
result = zip(name, age, hobby)
for item in result:
    print(item)
"""
('KeLi', 5, 'Bomb')
('WneDi', 2000, 'Beer')
('FuFu', 3000, 'Drama')
"""

如果要将结果储存到一个列表,则使用 list 自动转化为列表。

name = ["KeLi", "WenDi", "FuFu"]
age = [5, 2000, 3000]
hobby = ["Bomb", "Beer", "Drama"]
result = zip(name, age, hobby)
lst = list(result)
print(lst)
# [('KeLi', 5, 'Bomb'), ('WneDi', 2000, 'Beer'), ('FuFu', 3000, 'Drama')]

3.3.5 帮助函数help、dir

helpdir 函数分别可以查看数据类型的源码、能进行的操作。

s = "abcde"
help(str)
dir(s)

3.3.6 作用域相关 locals、globals

locals 用于查看当前作用域的变量, globals 用于查看全局变量。

3.3.7 排序 sorted

格式如下。

sorted(__iterable, key, reverse)
参数含义要求
__iterable排序对象可迭代
key排序规则函数
reverse升序降序bool
def func(x):
    return len(x)

name = ["DiLuke", "KeLi", "WenDi"]

result = sorted(name, key=func)
print(result) # ['Keli', 'WenDi', 'DiLuke']

可以与lambda表达式一起使用。详见3.11 匿名函数

name = ["DiLuke", "KeLi", "WenDi"]

result = sorted(name, key=lambda x: len(x))
print(result) # ['Keli', 'WenDi', 'DiLuke']

也可以对字典进行排序。

lst = [
    {"id": 1, "name": "ZhongLi", "age": 9999}
    {"id": 2, "name": "WenDi", "age": 2000}
    {"id": 3, "name": "KeLi", "age": 5}
]

result = sorted(lst, lambda d: d['age'])
print(result)
"""
[
    {"id": 3, "name": "KeLi", "age": 5},
    {"id": 2, "name": "WenDi", "age": 2000},
    {"id": 1, "name": "ZhongLi", "age": 9999}
]
"""

3.3.8 筛选 filter

filter函数可以筛选出列表中某些元素,并以生成器的形式返回,详见3.10生成器。格式如下。

filter(function, __iterable)
参数含义条件
function筛选条件函数
__iterable被筛选变量可迭代
lst = ["NaXida", "NaWeiaite", "Ying"]
f = filter(lambda x: x.startswith("N"), lst)
print(list(f)) # ['NaXida', 'NaWeilaite']

3.3.9 映射 map

map函数可以对所有元素进行相同处理,并以生成器的形式返回,详见3.10生成器。格式如下。

map(__func, __iterable)
参数含义条件
__func对元素进行的操作函数
__iterable被操作变量可迭代
lst = [1, 2, 3, 4, 5]

r = map(lambda x: x ** 2, lst)
print(list(r)) # [1, 4, 9, 16, 25]

3.4 作用域

分为全局变量局部变量,局部变量即在函数内定义的变量。想要在函数外引用变量,只能使用return。

3.5 函数嵌套

必须声明的一点:

函数可以作为返回值进行返回。

函数嵌套指在函数内再声明一个函数,此嵌套的函数同样不能在外面使用。如果要使用,只能通过直接返回这个函数(returm后可以跟一个函数)。

def func():
    def inner():
        print(123)
    return inner

b1 = func() # now b1 is the function innner.
b1()

值得注意的是,在以上例子,打印b1和inner函数的地址,会发现两者相同,说明此时b1就是inner函数。
同样地,传参时,参数也可以是一个函数。当一个函数以参数的形式在另一个函数中执行,这叫做代理模式

def func(an):
    an()

def target():
    print("I'm a target.")

func(target) # I'm a target.

3.6 函数与全局变量

如果要在函数内修改全局变量,则需要使用 global

a = 10
b = 10

def func1():
    a = 10

def func2():
    global b
    b = 20

print(a, b) # 10 20

以上例子中,在func1中的a = 10实际上是创建了局部变量a,并赋值10,而并非修改了全局变量a。
如果要在函数内找函数以外的局部变量,则需要使用 nonlocal 。此时会逐层向外寻找变量,但不包括全局变量。如果未找到此变量,则报错。

def func():
    a = 10
    b = 20
    def func2():
        nonlocal a
        a = 20
        b = 20
    func2()
    print(a, b) # 20 10

3.7 闭包

当将一个函数赋值给一个变量时,函数内的变量就会常驻于内存中,对其做出的改变将会被保存。本质如下。

内层函数对外层函数的局部变量的使用。

此时的内层函数被称为闭包函数。

def func():
    a = 10
    def inner():
        a += 10
        return a
    return inner

ret = func()

r1 = ret()
print(r1) # 11

r2 = ret()
print(r2) # 12

上面的例子中,a被封闭在func中,外部无法修改a的值,除非使用ret才行。这样便可以达到a如同一个全局变量的效果,且a无法被修改,除非使用指定的函数。这样便可以保护a。

3.8 装饰器

3.8.1 定义

装饰器本质上是一个闭包,作用如下。

在不改变原有函数调用的情况下,给函数增加新的功能。

形式如下。

def wrapper(fn):
    def inner():
        # before the function...
        fn()
        # after the function...
    return inner

表示方式是先定义一个闭包函数wrapper(),之后在需要装饰的函数前加 @wrapper ,也可以使用赋值的形式。

def add_cheater(game):
   def inner():
       print("Cheater started.")
       game()
       print("Cheater stopped.")
   return inner

@add_cheater
def play_lol():
    print("Legends never die!")

def play_genshin():
    print("Towards stars and gulfs!")

play_lol()
"""
Cheater started!
Legends never die!
Cheater stopped.
"""

play_genshin()
"""
Towards stars and gulfs!
"""

play_genshin = add_cheater(play_genshin)
play_genshin()
"""
Cheater started!
Towards stars and gulfs!
Cheater stopped.
"""

3.8.2 被装饰函数的参数

如果需要传递参数,则wrapper()需要做出改变,需要添加能接受任意数量参数的 *args**kwargs

def wrapper(fn):
    def inner(*args, **kwargs):
        # before the function...
        fn(*args, **kwargs)
        # after the function...
    return inner # don't add brackets!

3.8.3 被装饰函数的返回值

被装饰函数有返回值时,装饰器内也应该有返回。故通用装饰器写法如下。

def wrapper(fn):
    def inner(*args, **kwargs):
        # before the function...
        ret = fn(*args, **kwargs)
        # after the function...
        return ret
    return inner

@wrapper
def target():
    pass

target() # => inner()

3.8.4 多个装饰器

多个装饰器同时存在时,先引用的装饰器在更外层。

def wrapper1(fn):
    def inner(*args, **kwargs):
        print("wrapper1 started.")
        ret = fn(*args, **kwargs)
        print("wrapper1 ended.")
        return ret
    return inner

def wrapper2(fn):
    def inner(*args, **kwargs):
        print("wrapper2 started.")
        ret = fn(*args, **kwargs)
        print("wrapper2 ended.")
        return ret
    return inner

@wrapper1
@wrapper2
def target():
    print("I'm the target.")

target() # => inner()
"""
wrapper1 started.
wrapper2 started.
I'm the target.
wrapper2 ended.
wrapper1 ended.
"""
# order: w1 -> w2 -> t -> w2 -> w1

3.9 迭代器

3.9.1 迭代器使用

获取迭代器的两种方案

  1. iter() 内置函数可以直接拿到迭代器
  2. __iter()__ 特殊方法

如果使用迭代器超过可以迭代的次数,则报错。
同样地,进行一次迭代也有两种方案。

  1. next
  2. __next__
s = "Never gonna give you up~"
it1 = iter(s)
it2 = s.__iter__()

print(next(it1)) # N
print(next(it1)) # e
print(it2.__next__()) # N
print(it2.__next__()) # e

由此可以模拟for循环工作原理。

s = "Mamba"
it = iter(s)
while 1:
    try:
        data = next(it)
        print(data)
    except StopIteration:
        break
print("Finished!")
"""
M
a
m
b
a
Finished!
"""

以上例子中,try表示尝试运行代码,如果报错,则进入except后的内容,StopIteration表示错误类型为迭代器超过范围。

3.9.2 迭代器特性

  1. 本身可被迭代;
  2. 只能向前,不能反复;
  3. 节省内存;
  4. 惰性机制(只有在访问时才会移动)。

3.9.3 迭代器表达式

作用如下。

简化代码。

值得注意的是,由于元组不可修改,故元组没有推导式。如果出现了小括号内有表达式的情况,那是生成器表达式。

3.9.3.1 列表推导式

格式:[数据 for循环 if判断]

lst1 = [i for i in range(10) if i % 2 == 1]
print(lst) # [1, 3, 5, 7, 9]

lst2 = [f"item{i}" for i in range(3)]
print(lst2) # ['item0', 'item1', 'item2']

name = ["kevin", "tony", "tom"]
lst3 = [item.upper() for item in name]
print(lst3) # ['KEVIN', 'TONY', 'TOM']
3.9.3.2 集合推导式

格式:{数据 for循环 if判断}
与列表推导式用法相同。

3.9.3.3 字典推导式

格式:{k:v for循环 if判断}

lst = ["C", "C++", "Java"]
dic = {i: lst[i] for i in len(lst)}
# {0: 'C', 1: 'C++', 2: 'Java'}

3.10 生成器

3.10.1 特性

生成器的本质就是迭代器。

创建生成器函数的方案:

  1. 生成器函数;
  2. 生成器表达式。

3.10.2 生成器函数

生成器函数中有一个关键字 yield 。需要注意的是,yield只有在执行到next时才会返回数据。
生成器函数执行的时候,得到的是生成器,而不会执行函数。

def func():
    print(123456)
    yield 999

ret = func()
print(ret.__next__()) # 123456 999
print(ret.__next__()) # Error!

可以用yield实现函数分段执行,通过__next__()来执行下一段。

def func():
    print(123)
    yield 999
    print(456)
    yield 999

ret = func()
print(ret.__next__()) # 123 999
print(ret.__next__()) # 456 999
3.10.3 生成器表达式

格式:(数据 for循环 if判断)

gen = (i**2 for i in range(5))

for item in gen:
    print(item)

lst = list(gen)
print(lst) # []
# 0 1 4 9 16

值得注意的是,生成器的数据是一次性的。如上面的例子中,for循环已经拿空了生成器,所以后面的lst只能得到一个空列表。

3.11 匿名函数

可以认为是一个 lambda表达式。 可以简洁地创建一个函数,且无需声明其名字。

fn = lambda a, b: a + b
print(fn(13, 12)) # 25

它常与map、sorted等内置函数一起使用。

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值