Python重温笔记番外篇

1. 写在前面

今天这篇文章是python重温笔记的番外,整理一些面试中的问题以及遇到过的一些坑, 正好借着这个机会把前面的知识进行一个串联, 要不然这些知识很容易就会遗忘, 毕竟知识多而又不太容易常用到。 涉及到的知识包括列表推导式, 高阶函数的使用, 字典排序, 字符串, 日期, 文件遍历, 生成器, 正则, 线程等, 所以还是比较全面的, 以后如果再遇到python方面的练习题的话, 也可以再进行相应的补充。

2. python基础篇

2.1 一行代码生成奇数列表

一行代码生成[1, 2, 5, 7, 9, 11, 13, 15, 17, 19], 这个考察的是列表推导式, 比较简单

[i for i in range(1, 20) if i % 2 !=0]   # [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

2.2 等差数列

产生一个首项为 10,公差为 12,末项不大于 100 的列表, 这个是列表生成式

# 写一个等差数列
list(range(10, 100, 12))   #     [10, 22, 34, 46, 58, 70, 82, 94]

2.3 一行代码求1到10000内整数和

考察了高阶函数reduce的使用

# 一行代码求1到10000内整数和
sum(range(1, 10000))

from functools import reduce
reduce(lambda x, y: x+y, range(10000))  #     49995000

2.4 打乱一个列表

使用 random 模块,shuffle 函数打乱原来列表,值得注意是 in-place 打乱。

# 打乱一个列表
import random
a = list(range(10))
random.shuffle(a)
a   #   [2, 4, 5, 7, 9, 8, 0, 3, 6, 1]

2.5 字典按照value排序返回新字典

考察的字典的排序, sortedkey方法

# 字典按照value排序并且返回新字典
d = {'a':12, 'b':50, 'c':1, 'd':20}

dict(sorted(d.items(), key=lambda x: x[1]))   #{'c': 1, 'a': 12, 'd': 20, 'b': 50}

2.6 删除list的重复元素, 保证顺序不变

如果只是删除重复元素,直接使用内置 set 函数,去重,但是不能保证原来元素顺序。

# 如何删除list里面重复元素, 并且保证顺序不变
b = []
a = [3, 2, 2, 2, 1, 3]
for i in a:
    if i not in b:
        b.append(i)
b   #     [3, 2, 1]

2.7 找出两个列表中的相同和不同元素

这个考察的是集合的交, 并运算, 给定列表 a = [3,2,2,2,1,3],列表 b = [1,4,3,4,5],使用集合,找出相同元素:

# 怎么找到两个列表的相同元素和不同元素
a = [3, 2, 2, 2, 1, 3]
b = [1, 4, 3, 4, 5]

# 集合的交
def ana(a, b):
    aset, bset = set(a), set(b)
    same = aset.intersection(bset)
    differ = aset.difference(bset).union(bset.difference(aset))
    return same, differ
ana(a, b)  #     ({1, 3}, {2, 4, 5})

2.8 把字符串处理成字典

输入串 "k0:10|k1:2|k2:11|k3:5",输出字典 {k0:10,k1:2,...}

  • 第一层 split,根据分隔符 |,分割出 k0:10,k1:2,k2:11,k3:5
  • 第二层 split,根据分隔符 :,分割出新字典的键值对

这个可以使用map函数。

# 字符串处理成字典   
s = "k0:10|k1:2|k2:11|k3:5"
d = {mi[0]:mi[1] for mi in map(lambda x: x.split(':'), s.split('|'))}
d  #   {'k0': '10', 'k1': '2', 'k2': '11', 'k3': '5'}

2.9 输入日期, 判断是一年的第几天

这个考察datetime模块, 使用 datetime 模块,提取日期 date 对象,调用 timetuple() 方法,返回一个 struct_time 对象,属性 tm_yday 便是这一年的第几天:

# 输入日期, 判断这一天是这一年的第几天
from datetime import datetime

def get_day_of_year(y, m, d):
    return datetime(y, m, d).date().timetuple().tm_yday

get_day_of_year(2020, 2, 1)     #     32

2.10 遍历目录和子目录, 抓取某个特定后缀名的文件

os 模块walk 方法实现递归遍历所有文件,os.path.splitext 返回文件的名字和扩展名,如果扩展名匹配到 ext,则添加到 res 中。

# 遍历目录与子目录, 抓取.py文件
import os

def get_files(directory, ext):
    res = []
    for root, dirs, files in os.walk(directory):
        print(root, dirs, files)   # root是遍历目录的当前路径, dirs是该路径下的目录, files是该路径下的文件
        for filename in files:
            name, suf = os.path.splitext(filename)
            if suf == ext:
                res.append(os.path.join(root, filename))  
    return res

## 上面函数的执行过程就是从传入的目录开始, 得到传入的目录, 该目录下的子目录和该目录下的文件, 对于该目录下文件再次进行遍历, 查找相应后缀名
## 的目录, 然后再遍历传入目录的子目录, 依然是上面的那种套路进行查找
get_files('E:/Jupyter Notebook/Python全栈60天', '.png')

结果如下:

E:/Jupyter Notebook/Python全栈60天 ['.ipynb_checkpoints', 'img', 'Python60天专栏录制短动画'] ['Day1-Day2.ipynb', 'Day10_python文件操作案例.ipynb', 'Day11_python时间模块的使用总结.ipynb', 'Day17_Python列表生成式高效使用的案例.ipynb', 'Day18_Python对象间的相等性比较等使用总结.ipynb', 'Day19_yield关键字和生成器, nonlocal关键字和global关键字总结.ipynb', 'Day20_Python函数的5类参数.ipynb', 'Day21_迭代器和生成器.ipynb', 'Day22_多线程和协程.ipynb', 'Day24—Python.ipynb', 'Day3-Day4.ipynb', 'Day5-Day6.ipynb', 'Day7-Day8.ipynb', 'Day9_字符串操作与正则.ipynb', 'Day_23_python的Collections.ipynb', 'test.py']
E:/Jupyter Notebook/Python全栈60天\.ipynb_checkpoints [] ['Day1-Day2-checkpoint.ipynb', 'Day10_python文件操作案例-checkpoint.ipynb', 'Day11_python时间模块的使用总结-checkpoint.ipynb', 'Day17_Python列表生成式高效使用的案例-checkpoint.ipynb', 'Day18_Python对象间的相等性比较等使用总结-checkpoint.ipynb', 'Day19_yield关键字和生成器, nonlocal关键字和global关键字总结-checkpoint.ipynb', 'Day20_Python函数的5类参数-checkpoint.ipynb', 'Day21_迭代器和生成器-checkpoint.ipynb', 'Day22_多线程和协程-checkpoint.ipynb', 'Day24—Python-checkpoint.ipynb', 'Day3-Day4-checkpoint.ipynb', 'Day5-Day6-checkpoint.ipynb', 'Day7-Day8-checkpoint.ipynb', 'Day9_字符串操作与正则-checkpoint.ipynb', 'Day_23_python的Collections-checkpoint.ipynb']
E:/Jupyter Notebook/Python全栈60天\img ['.ipynb_checkpoints', '1_2', '3_4', '4_5', '9_10'] ['1.png']
E:/Jupyter Notebook/Python全栈60天\img\.ipynb_checkpoints [] []
E:/Jupyter Notebook/Python全栈60天\img\1_2 [] ['1.gif', '1.png', '2.png', '3.gif', '3.png', '4.png', '5.png', '6.png', '7.png']
E:/Jupyter Notebook/Python全栈60天\img\3_4 [] ['1.gif', '1.png', '10png.png', '11.png', '12.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8png.png', '9.png']
E:/Jupyter Notebook/Python全栈60天\img\4_5 [] ['1.png']
E:/Jupyter Notebook/Python全栈60天\img\9_10 [] ['1.png', '2.png', '3.png', '4.png', '5.png', '6.png']
E:/Jupyter Notebook/Python全栈60天\Python60天专栏录制短动画 [] ['Day19-2.mp4', 'Day19-3.mp4', 'Day19.mp4', 'Day2.mp4', 'Day21-2.mp4', 'Day21.mp4', 'Day4.mp4', 'Day6.mp4', 'Day7.mp4']


['E:/Jupyter Notebook/Python全栈60天\\img\\1.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\1.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\2.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\3.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\4.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\5.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\6.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\1_2\\7.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\3_4\\1.png',
 'E:/Jupyter Notebook/Python全栈60天\\img\\3_4\\10png.png']

3. Pyhon 进阶篇

3.1 单机4G内存, 处理10G文件的方法

# 单机4G内存, 处理10G文件的方法
def python_read(filename):
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            yield line

# pandas的read_csv, 这个方法更加的灵活
def pandas_read(filename, sep=',', chunksize=5):
    reader = pd.read_csv(filename, sep=sep, chunksize=chunksize)
    while True:
        try:
            yield reader.get_chunk()
        except StopIteration:
            print('---Done---')
            break

3.2 统计一个文本单词频次最高的10个单词

使用 yield 解耦数据读取 python_read 和数据处理 process

  • python_read:逐行读入
  • process:正则替换掉空字符,并使用空格,分隔字符串,保存到 defaultdict 对象中。
# 统计一个文本单词频次最高的10个单词
def python_read(filename):
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            yield line

d = defaultdict(int)

def process(line):
    for word in re.sub('\W', " ", line).split():
        d[word] += 1

# 使用两个函数,最后,使用 Counter 类统计出频次最高的 10 个单词:
for line in python_read('write_file.py'):
    process(line)

most10 = Counter(d).most_common(10)
print(most10)

3.3 反转一个整数

这个得考虑的全面一些。 主要逻辑如下:

  • 如果 x 位于 (-10,10) 间,直接返回;
  • 然后,将 x 转换为字符串对象 sx;
  • 如果 x 是负数,截取 sx[1:],并反转字符串;
  • 如果 x 是正数,直接反转字符串;
  • 最后使用内置函数 int() 转化为整数。
# 反转一个整数  
def reverse_str(sx):
    return sx[::-1]

def reverse_int(x:int):
    # 如果在-10-10之间, 直接返回
    if -10 < x < 10:
        return x
    
    sx = str(x)
    
    # 如果x是负数, 那么就反转后面的
    if sx[0] == '-':
        sx = reverse_str(sx[1:])
        x = int(sx)
        return -x
    
    sx = reverse_str(sx)
    return int(sx)

reverse_int(-1)   # -1
    

3.4 判断输出结果

# 看下面函数的执行结果
def f():
    i = 0
    def foo(x):
        return i*x
    rtn = []
    while i < 3:
        rtn.append(foo)   # rtn 添加三个函数 foo,但是并未发生调用。
        i += 1
    return rtn

for fs in f():
    print(fs(10))
    
# 直到执行 fs(10) 时,内嵌函数 foo 才被调用,但是此时的 enclosing 变量 i 取值为 3:
30
30
30

这个要注意, 内嵌函数 foo 使用的两个变量 i 和 x,其中 x 为其形参,i 为 enclosing 域内定义的变量。rtn 添加三个函数 foo,但是并未发生调用。

3.5 判断函数的形参调用

已知 filename 为 ‘.’,c 为 10,正确为 foo 函数传参的方法,以下哪些是对的,哪些是错误的?

# 如下函数foo的调用哪些是正确的?
def foo(filename, a=0, b=1, c=2):
    print('filename: %s \n c:%d' %(filename, c))

foo('.', 10)     # 错误,a 被赋值为 10
filename: . 
 c:2
foo('.', 0, 1, 10) # 正确,c 是位置参数
filename: . 
 c:10
foo('.', 0, 1, c=10) # 正确,c 是关键字参数
filename: . 
 c:10
foo('.', a=0, 1, 10)  # 错误,位置参数不能位于关键字参数后面
  File "<ipython-input-5-c704ccbf612c>", line 1
    foo('.', a=0, 1, 10)
                 ^
SyntaxError: positional argument follows keyword argument
foo(filename='.', c=10)   # 正确,filename 和 c 都是关键字参数
foo('.', c=10)    # 正确,filename 位置参数,c 是关键字参数
filename: . 
 c:10
filename: . 
 c:10

3.6 lambda函数的形参和返回值

key值为lambda函数, 说说lambda函数的形参和返回值

def longer(*s):
    return max(*s, key=lambda x: len(x))
longer({1, 2, 5, 7}, {1, 5, 7}, {2, 4, 6, 7, 8})   #     {2, 4, 6, 7, 8}
  • lambda 函数的形参:s 解包后的元素值,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 三种。
  • lambda 函数的返回值为:元素的长度,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 的长度 4,3,5。

3.7 正则匹配负整数

匹配所有负整数, 不包括0. 正则表达式: ^-[1-9]\d*$

  • ^-表示字符串以-开头
  • [1-9]表示数字1到9, 注意不要写成\d, 因为负整数没有-0开头的
  • \d*表示数字0到9出现0次, 1次或者多次
  • $ 表示字符串以数字截尾

在这里插入图片描述

import re
s = ['-1', '-15768', '9', '-01', '10', '-']
pat = r'^-[1-9]\d*$'
rec = re.compile(pat)
rs = [i for i in s if rec.match(i)]
rs  #   ['-1', '-15768']

3.8 正则匹配负浮点数

正确写出匹配负浮点数的正则表达式,要先思考分析。

考虑到两个实例:-0.12、-111.234,就必须要分为两种情况。

  • 适应实例-0.12的正则表达式, ^-0.\d*[1-9]\d*$, 注意要考虑到 -0.0000 这种非浮点数,因此正则表达式必须这样写。不要想当然的写^-0.\d*$, ^-0.\d*[1-9]*$, 或者^-0.\d*[0-9]$, 因为这几个都会匹配-0.
  • 适应实例-111.234的正则, ^-[1-9]\d*.\d*$

使用|, 综合两种情况即可: ^-0.\d*[1-9]\d*$|^-[1-9]\d*.\d*$
在这里插入图片描述

import re
s = ['-1', '-1.5756', '-0.00', '-000.1', '-1000.10']
pat = r'^-0.\d*[1-9]\d*|^-[1-9]\d*.\d*$'
rec = re.compile(pat)
rs = [i for i in s if rec.match(i)]
rs   #    ['-1.5756', '-1000.10']

3.9 使用filter()求出列表中大于10的元素

filter 函数使用 lambda 函数,找出满足大于 10 的元素。

a = [15, 2, 7, 20, 400, 10, 9, -15, 107]
list(np.array(a)[np.array(a)>10])

list(filter(lambda x: x>10, a))   #  [15, 20, 400, 107]

3.10 说说下面map函数的输出结果

m = map(lambda x, y: min(x, y), [5, 1, 3, 4], [3, 4, 3, 2, 1])
list(m)  # [3, 1, 3, 2]

# map 函数当含有多个列表时,返回长度为最短列表的长度;

3.11 说说reduce函数的输出结果

from functools import reduce
reduce(lambda x, y: x*y+1, [1, 2, 3, 4, 5])  # 206

3.12 x=(i for i in range(5)), x是什么类型?

x是生成器类型, 与for等迭代

x = (i for i in range(5))
next(iter(x))   # 0

3.13 可变类型和不可变类型分别列举三个:

  • 可变类型: 列表, 字典, 集合, deque
  • 不可变类型: 字符串, 整型, 浮点, 元组等

只有不可变类型才能作为字典等的键

3.14 is 和==有什么区别?

  • is: 用来判断两个对象的标识号是否相等
  • ==: 用来判断值或者内容是否相等, 默认是基于两个对象的标识号比较

也就是说,如果 a is b 为 True 且如果按照默认行为,意味着 a==b 也为 True。

3.15 写一个学生类Student

添加一个属性id, 并实现id相等, 则认为是同一位学生的功能

class Student:
    def __init__(self, id, name):
        self.id = id
        self.name = name
    def __eq__(self, student):
        return self.id == student.id
s1 = Student(10, 'xiaoming')
s2 = Student(20, 'xiaohong')
s3 = Student(10, 'xiaoming2')

s1==s2  # False
s1==s3 # True

3.16 有什么方法获取类的所有属性和方法?

获取下面类 Student 的所有属性和方法,使用 dir() 内置函数。

class Student:
    def __init__(self,id,name):
        self.id = id
        self.name = name
    def __eq__(self,student):
        return self.id == student.id
dir(Student)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
dir(s1)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'id',
 'name']

3.17 python如何动态或者和设置对象的属性

class Student:
    def __init__(self,id,name):
        self.id = id
        self.name = name
    def __eq__(self,student):
        return self.id == student.id
# Python 使用 hasattr 方法,判断实例是否有属性 x:
hasattr(s1, 'id')
hasattr(s1, 'address')

#使用 setattr 动态添加对象的属性,函数原型:
if not hasattr(s1, 'address'):
    setattr(s1, 'address', 'beijing')
    print(hasattr(s1, 'address'))  #  True
dir(s1)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'address',
 'id',
 'name']
s4 = Student(12, 'wu')
dir(s4)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'address',
 'id',
 'name']

3.18 实现一个按照2* i+1自增的迭代器

实现类AutoIncrease, 继承于Iterator对象, 然后从写两个方法:

  • iter
  • next
from collections.abc import Iterator

class AutoIncrease(Iterator):
    def __init__(self, init, n):
        self.init = init
        self.n = n
        self.__cal = 0
    
    def __iter__(self):
        return self
    def __next__(self):
        if self.__cal == 0:
            self.__cal += 1
            return self.init
        while self.__cal < self.n:
            self.init *= 2
            self.init += 1
            self.__cal += 1
            return self.init
        raise StopIteration
iter = AutoIncrease(1, 10)
for i in iter:
    print(i)
1
3
7
15
31
63
127
255
511
1023

3.19 实现文件按行读取和操作数据分离

使用 yield 解耦按行读取和操作数据的两步操作:

def read_line(filename):
    with open(filename, 'r', encoding='utf-8') as f:
        for line in f:
            yield line

def process_line(line: str):
    pass

for line in read_line('.'):
    process_line(line)

3.20 使用python锁避免脏数据出现的例子

使用多线程编程,会出现同时修改一个全局变量的情况,创建一把锁 locka:

import threading
import time

locka = threading.Lock()
a = 0
def add1():
    global a
    try: 
        locka.acquire()   # 获得锁
        tmp = a + 1
        time.sleep(0.2)   #  模拟IO操作
        a = tmp
    finally:
        locka.release()   # 释放锁

threads = [threading.Thread(name='t%d'%(i,),target=add1) for i in range(10)]
[t.start() for t in threads]

# 多线程的代码,由于避免脏数据的出现,基本退化为单线程代码,执行效率被拖累。

3.21 说说死锁, GIL锁和协程

多个子线程在系统资源竞争时,都在等待对方解除占用状态。

比如,线程 A 等待着线程 B 释放锁 b,同时,线程 B 等待着线程 A 释放锁 a。在这种局面下,线程 A 和线程 B 都相互等待着,无法执行下去,这就是死锁。

为了避免死锁发生,Cython 使用 GIL 锁,确保同一时刻只有一个线程在执行,所以其实是伪多线程。

所以,Python 里常常使用协程技术来代替多线程。多进程、多线程的切换是由系统决定,而协程由我们自己决定。协程无需使用锁,也就不会发生死锁。同时,利用协程的协作特点,高效的完成了原编程模型只能通过多个线程才能完成的任务。

4. python中容易忽略的坑点整理

这个模块整理下之前在python里面遇到的一些容易出错且忽略的一些点:

  1. 删除列表元素
    这个是一个比较简单的问题, 可以越简单,我们往往就会越忽略一些东西, 删除列表元素, 就是给定一个列表, 要求删除指定元素, 比如[1,3,5,3,2], 要求删除里面的3, 我们可能会写出这样的代码:

    def del_item(lst,e):
        for item in lst:
            #print(item)
            if item == e:
                lst.remove(item)
        return lst
    

    我们的思路就是遍历一遍列表, 如果元素等于指定的元素, 我们就执行删除(注如果单纯的用remove或者pop只会删除某一个元素), 这样的思路确实是没有问题, 但是内部真的是按照我们想的执行吗? 其实不是的, 边遍历边删除是一个危险的思想, 这时候每删除一个元素, 移掉位置 i 后的所有元素索引都要减一, 这时候其实就会跳过一些元素没有被检查, 可以打印一下item试试。 正确的做法:找到被删除元素后,删除,同时下次遍历索引不加一;若未找到,遍历索引加一

    def del_item2(lst,e):
        i = 0
        while i < len(lst):
            if lst[i] == e:
                lst.remove(lst[i])
            else:
                i += 1
        return lst
    

    当然, 也有一个简单的方式, 如果会filter这个函数的话, 一行代码就可以搞定:

    list(filter(lambda x: x!=e, lst))
    
  2. 函数默认参数为空
    Python 函数的参数可设为默认值。如果一个默认参数类型为 list,默认值为设置为 []。这时候会有问题吗? 比如下面这个例子:

    def delta_val(val, volume=[]):
        if volume is None:
            volume = []
        size = len(volume)
        for i in range(size):
            volume[i] = i + val
        return volume
    

    面试的时候经常会问到的一个题目, 有问题吗? 肯定是有的, 我们可以进行一个测试:

    lst1 = delta_val(10)
    lst1   # []    这是个空
    
    lst1.append(1)
    lst1.append(2)   
    lst1   # [1, 2] 
    
    #  貌似没有发现任何问题, 可是我们再重新建立一个新的列表
    lst2 = delta_val(10)
    lst2   # [10, 11]  会发现lst2的初始值直接变成了[10, 11]  而我们想要的是[], 所以问题出现在了这里
    

    原来调用函数 delta_val 时,默认参数 volume 取值为默认值时,并且 volume 作为函数的返回值。再在函数外面做一些操作,再次按照默认值调用,并返回。整个过程,默认参数volume 的 id 始终未变。

  3. 解包
    Python 中,支持多值赋值给多变量的操作。最常见的用法,一行代码交换两个变量:

    In [34]: a, b = 1, 2
    In [35]: a, b = b, a
    

    但是,面对稍微复杂点的类似操作,如果不搞懂多值赋值的执行顺序,就会掉入陷阱。如下例子,如果心算出的结果等于 a = 3, b = 5,那么就说明没弄明白执行顺序。

    In [38]: a, b = 1, 2
    In [39]: a, b = b+1, a+b
    

    记住一点:多值赋值是先计算出等号右侧的所有变量值后,再赋值给等号左侧变量。所以,答案应该是:a = 3, b = 3

    这种多值赋值,是一种解包(unpack)操作。

    既然是解包,那么就得先有打包。的确,等号右侧的多个变量,会被打包(pack)为一个可迭代对象。

    赋值操作,就相当于解包。这种解包操作,有时非常有用。比如,foo 函数返回一个 list,如下:

    def foo():
        result = [1,'xiaoming','address','telephone',['','','...']]
        return result 
    

    但是,我们只需要列表中的前两项。更为简洁、紧凑的做法:等号左侧定义两个我们想要的变量,其他不想要的项放到 others 变量中,并在前加一个 *,如下所示:

    sid, name, *others = foo()
    
    In [64]: sid
    Out[64]: 1
    
    In [65]: name
    Out[65]: 'xiaoming'
    

    *others 会被单独解析为一个 list:

    In [66]: others
    Out[66]: ['address', 'telephone', ['', '', '...']]
    

目前先整理这么多,python语言也是博大精深,后面遇到新内容会随时补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/294059.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Databend 的算力可扩展性

作者&#xff1a;尚卓燃&#xff08;PsiACE&#xff09; 澳门科技大学在读硕士&#xff0c;Databend 研发工程师实习生 Apache OpenDAL(Incubating) Committer PsiACE (Chojan Shang) GitHub 对于大规模分布式数据处理系统&#xff0c;为了更好应对数据、流量、和复杂性的增长…

湖南大学-数据库系统-2023期末考试【原题】

前言 早上11&#xff1a;00考完的考试&#xff0c;下午回来打了三把LOL之后&#xff0c;凭着回忆把题目重现出来了。 在复习的时候刷了15&#xff0c;16&#xff0c;17&#xff0c;18&#xff0c;19&#xff0c;21六年的卷子&#xff0c;感觉题目都差不多&#xff0c;但是难度…

BAT036:TXT与DOC格式互转、DOC与DOCX格式互转

引言:编写批处理程序,可实现txt与doc文档格式互转、doc与docx文档格式互转。 一、新建Windows批处理文件 参考博客: BAT002:在右键菜单新建中添加【Windows批处理文件】_为右键菜单添加bat-CSDN博客 二、TXT与DOC格式互转 1.右键新建的批处理文件,点击【编辑】。 ​ …

让电脑变得更聪明——用python实现五子棋游戏

作为经典的棋类游戏&#xff0c;五子棋深受大众喜爱&#xff0c;但如果仅实现人与人的博弈&#xff0c;那程序很简单&#xff0c;如果要实现人机对战&#xff0c;教会计算机如何战胜人类&#xff0c;那就不是十分容易的事了。本文我们先从简单入手&#xff0c;完成五子棋游戏的…

ES两个小时没连接竟然会出现bug,为此老板给我夹了个鸡腿。。。

前言 前段时间上线了个项目&#xff0c;测试每天早上来摸鱼之前会点一点&#xff0c;发现第一次点会报错&#xff0c;然后一天都没问题&#xff0c;刚开始没在意&#xff0c;后来每天上班来摸鱼前点第一次都会出错&#xff0c;发现真的摸到鱼了&#xff0c;然后就给我提了个bu…

深耕汽车检测设备领域,引领行业技术革新

在汽车工业飞速发展的今天&#xff0c;汽车检测技术作为保障车辆安全、提升维修效率的重要手段&#xff0c;日益受到行业内外的高度关注。康士柏汽车检测线设备厂家&#xff0c;作为这一领域的佼佼者&#xff0c;凭借其深厚的技术积累和卓越的产品品质&#xff0c;正引领着行业…

CSS基础笔记-01CSS概述

文章目录 前言CSS是什么CSS的作用CSS语法添加CSS的方法 前言 CSS是什么&#xff1f;有什么作用&#xff1f;怎么编写CSS&#xff1f;怎样添加CSS&#xff1f;本文对CSS的四个方面作了学习并形成学习笔记。 CSS是什么 CSS &#xff08;Cascading Style Sheets&#xff0c;层叠…

java字节码

1. 字节码 1.1 什么是字节码&#xff1f; Java之所以可以“一次编译&#xff0c;到处运行”&#xff0c;一是因为JVM针对各种操作系统、平台都进行了定制&#xff0c;二是因为无论在什么平台&#xff0c;都可以编译生成固定格式的字节码&#xff08;.class文件&#xff09;供…

小寒节气吃什么?来一道烤排骨吧!

小寒节气是中国传统二十四节气中的第23个节气。 在寒冷的冬季&#xff0c;为了驱寒保暖&#xff0c;人们会选择一些具有温热性质的食物来进补。那么&#xff0c;小寒节气应该吃什么呢&#xff1f;羊肉是冬季进补的佳品。羊肉富含丰富的蛋白质和热量&#xff0c;能够帮助身体抵…

Go语言并发模式视角思考

犹记得2019年中旬进行知识点的学习和demo的练习&#xff0c;熟悉各种语法和并发调度的场景&#xff0c; 在2019年末开始参与项目实战开发和逻辑梳理 Go语言的接触也是更多探索和业务的拆件&#xff0c;做一些雏形工具&#xff0c;来慢慢的孵化业务生态 后来陆陆续续&#xff…

03- OpenCV:矩阵的掩膜操作

目录 1、矩阵的掩膜操作 简介 2、获取图像像素指针 3、掩膜操作解释 4、代码演示 1、矩阵的掩膜操作 简介 在OpenCV中&#xff0c;矩阵的掩膜操作是一种通过使用一个二进制掩膜来选择性地修改或提取图像或矩阵的特定区域的方法。 掩膜是一个与原始图像或矩阵具有相同大小的…

力扣题:高精度运算-1.3

力扣题-1.3 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;43. 字符串相乘 解题思想&#xff1a;类似计算时采用的竖式乘法。首先取得num2的低位&#xff0c;并补齐对应的0&#xff0c;然后与num1进行相乘&#xff0c;然后进行字符串的相加操作。…

【萤火虫系列教程】2/5-Adobe Firefly 文字​生成​图像

文字​生成​图像 登录账号后&#xff0c;在主页点击文字生成图像的【生成】按钮&#xff0c;进入到文字生成图像 查看图像 在文字生成图像页面&#xff0c;可以看到别人生成的图像。 点击某个图像&#xff0c;就可以进入图像详情&#xff0c;可以看到文字描述。 生成图像 我…

c++之迭代器

目录 一、迭代器 二、几种常见的迭代器类型 三、使用迭代器时注意事项 一、迭代器 在C中&#xff0c;迭代器是一种用于遍历容器元素的对象。迭代器提供了一种通用的方式来访问各种不同类型的容器&#xff0c;如数组、向量、列表、集合和映射等。 使用迭代器可以避免直接操作…

c++牛客总结

一、c/c语言基础 1、基础 1、指针和引用的区别 指针是一个新的变量&#xff0c;指向另一个变量的地址&#xff0c;我们可以通过这个地址来修改该另一个变量&#xff1b; 引用是一个别名&#xff0c;对引用的操作就是对变量本身进行操作&#xff1b;指针可以有多级 引用只有一…

python股票分析挖掘预测技术指标知识大全(1)

本人股市多年的老韭菜&#xff0c;各种股票分析书籍&#xff0c;技术指标书籍阅历无数&#xff0c;萌发想法&#xff0c;何不自己开发个股票预测分析软件&#xff0c;选择python因为够强大&#xff0c;它提供了很多高效便捷的数据分析工具包&#xff0c; 我们已经初步的接触与…

leetcode 每日一题 2024年01月01日 经营摩天轮的最大利润

题目 1599 经营摩天轮的最大利润 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱&#xff0c;但每次轮转都需要支付一定的运行成本 runningCost 。摩天轮每次轮转都恰好转动 1 / 4 周。 给你…

LeetCode 2487. 从链表中移除节点:单调栈

【LetMeFly】2487.从链表中移除节点&#xff1a;单调栈 力扣题目链接&#xff1a;https://leetcode.cn/problems/remove-nodes-from-linked-list/ 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1&#xff1a; 输…

【RocketMQ每日一问】RocketMQ中raft的应用?

1.rocketmq中raft算法实现方式 RocketMQ 中实现 Raft 算法的模块是 DLedger&#xff0c;它是一种基于 Raft 协议的分布式日志存储模式&#xff0c;用于提供高可用性和数据一致性的保证&#xff0c;保证消息的可靠性和持久化存储。 在 DLedger 中&#xff0c;每个节点都维护着…