Python有一个很神奇的取巧技巧

a,b = b,a

这样就可以完成数据的交换,而不需要使用函数swap,或者其他的交换方式,那么这个操作究竟怎么实现,而思考又是什么呢?

'''
创建a,b两个变量
'''
a = 1
b = 3
print(a,b)

Output: 1 3

'''
交换a,b=b,a,发现他们的数据进行了对调
本能的以为,是不是进行了地址交换
但是需要思索一下,C语言的swap是不是
swap(&a, &b){
    temp = a;
    a = b;
    b = temp;
}
这样的方式,而Python,是没有temp的,所以需要继续思考下去
'''
a,b = b,a
print(a,b)

Output: 3 1

'''
我们创建一个list = [1,2,3,4,5]
同时创建一个i用来索引这个list
li[i] = 第一个数字,1
'''
li = [1,2,3,4,5]
i = 0
print(li,i)

Output: [1, 2, 3, 4, 5] 0

'''
eg1.
这里,我们将第一个元素:1和第li[1]个元素(也就是第二个元素),2进行交换
理论上应该得到一数据
[2,1,3,4,5]
然而事实上确实[2,2,1,4,5],与概念发生了偏差
'''
li[i], li[li[i]] = li[li[i]], li[i]
print(li,i)

Output: [2, 2, 1, 4, 5] 0

'''
eg2.
对刚刚的数据在做一个同类型的实验
'''
li2 = [1,2,3,4,5]  # 创建的是li2
i = 0
li2[li2[i]], li2[i] = li2[i], li2[li2[i]]
print(li2,i)

Output: [2, 1, 3, 4, 5] 0

现象

发现他们的数据仅仅是一个顺序不同而不一样了,猜测第一个实验eg1.应该是对li[i]率先进行了赋值,导致li[i]提前编程了2,而li[li[i]] 编程了li[2]则变成了第三个元素,故li[i] = 2 而li[li[i]] = 最开始的1

那么问题来了

如果仅仅是通过指针进行了内存地址的改变,不应该在li[i] 赋值了2之后,li[li[i]] 也应该变为2么?而却事实上发生了交换变成了li[i]最开始的状态即为1

# 翻阅官方的说米文档: https://docs.python.org/3/library/dis.html
'''
回到一开始的a,b = b,a
python在多参数赋值的时候,会将数据打包成一个元组(tuple),元组是不可以修改的具有保护特性
即 a,b = (b, a)
再进行元组拆包工作
a = b_old 
b = a_old

而元组拆包的思想,其实就是把新变量放进一个栈中,旧的元组放进一个栈中
依次输出栈顶元素进行一一匹配

注意不同结构见也可以操作,由于python的等于号非常的灵活
'''

# 创建了一个data的list数据,其中包括了,字符串,数字,元组
data = ['abcd',11,2,(1,2,3)]
x1,x2,x3,x4 = data
print(x1)
print(x2)
print(x3)
print(x4)

output:

abcd
11
2
(1, 2, 3)

对其中的内容再做拆分也是可以的

# 其中x4又可以拆分
y1,y2,y3 = x4
print(y1)
print(y2)
print(y3)

Output:

1
2
3

总结

其实这个特性要注意,并且在使用中要留意数据的类型对齐,否则可能出现潜在BUG,由于Python的函数返回值是默认多返回值的,所以也因为这个特性能够节省很多函数返回值的而外设计,比如C语言中,要想实现一个函数同时返回多个值

1.要么创建一个数据结构,把多函数返回值框死 2.要么使用数据结构字典,将多参数作为字典映射的方式传递出来

而Python只需要 a,b = func(x) 这样

 

Python也可以自建数据结构,如果你用C,JAVA,C++,C#这类语言,做自建数据结构应该挺频繁的,而Python就基本用默认的那些,这也得益于Python灵活的特性,不需要建立那么多数据结构,反而还不如建立基类

分类: PYTHON

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注