您的位置:首页 > 编程语言 > Python开发

python 实例详解map()函数、lambda函数、二进制移位--生成和2的次方有关的矩阵

2019-05-26 09:51 721 查看
版权声明:转载请注明出处----译心 https://blog.csdn.net/Yixin_Hu/article/details/90555903

一、map()函数

1、map() 会根据提供的函数对指定序列做映射。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
  map(func,iterables)
2、其中iterables是迭代函数的意思,也就是要执行function的序列。在python 3x中,map函数生成的map() 生成的是迭代器不是list,直接运行会提示“<map at 0x1fb2382ce10>”一类的信息,如下第一行代码;如果要生成list,可以在map前加上list,即list(map()),如下第二行代码。

map(sum,([1,2],[3,4]))
list(map(sum,([1,2],[3,4])))

3、以下是更多map()的使用实例。

>>>def square(x) :            # 计算平方数
...     return x ** 2
...
>>> map(square, [1,2,3,4,5])   # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]

# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]

总之,在需要对序列的每一个元素进行操作时,map()是个不错的选择。

二、lambda函数

Lambda函数又称匿名函数,匿名函数就是没有名字的函数,在实际运用中主要用于只使用一次,功能较为简单的函数。
  lambda argument_list: expression
   argument_list即参数列表,expression指函数的具体表达。如最简单的lambda函数。

>>> lambda x :x+1
<function <lambda> at 0x000001E2703B9D90>
#因为lambda是匿名函数,如果单独运行它的话要给它一个名字。
>>> add = lambda x :x+1
>>> add(2)
3

关于具体的使用方法和场景,可以参见以下博客:
https://www.cnblogs.com/huangbiquan/p/8030298.html

三、二进制移位

“>>‘”和“<<”都是位运算,对二进制数进行移位操作。
①“<<” 是左移,末位补0,类比十进制数在末尾添0相当于原数乘以10,
x<<1是将x的二进制表示左移一位,相当于原数x乘2。
整数4在二进制下是100,4<<1左移1位变成1000(二进制),结果是8。

>>> 2<<1
4
>>> 4<<1
8

②“>>‘”是右移,右移1位相当于除以2。
③>>=和<<=,就是对变量进行位运算移位之后的结果再赋值给原来的变量,可以类比赋值运算符+=和-=可以理解。
比如x>>=2, 就是把变量x右移2位,再保留x操作后的值。

>>> x = 4
>>> x>>=2
>>> x
1

二进制移位在涉及2的次方的运算时可以简化代码,非常方便。

四、实例讲解

(一)解析需求

实现一个函数make_mat(n),创建类似如下的矩阵:
[[1, 2, 4, 8, 4, 2, 1],
[2, 4, 8, 16, 8, 4, 2],
[4, 8, 16, 32, 16, 8, 4],
[8, 16, 32, 64, 32, 16, 8],
[4, 8, 16, 32, 16, 8, 4],
[2, 4, 8, 16, 8, 4, 2],
[1, 2, 4, 8, 4, 2, 1],]
参数:n
返回值:一个长度为n的列表,这个列表里面的元素都是长度为n的列表
(相当于n*n的一个二维表),规律和2的次方有关(自己找吧)。
上面给出的例子是调用make_mat(7)的结果。

解析:
从题目中可以看出,要求实现给定一个n值,输出一个矩阵,其中矩阵内有n个列表,每个列表有n个元素,每个元素与前一个存在2次方关系。

(二)解答方法

1、方法一:
算法NS图如下:

源码如下:

def make_mat(n):
l=n//2
#l是作为分界点,将ii,jj与其比较,判断是应该乘以还是除以2.
ls=[]
#输出列表首先为空
for i in range(n):
ls.append([])
#对于给定的n,有n个子列表。每循环一次,添加一个子列表。
for j in range(n):
ii,jj=i,j
if i>=l:
ii=n-1-i
if j>=l:
jj=n-1-j
#如果i,j小于l,则乘以二,即二进制左移一位
ls[i].append(1<<(ii+jj))
return ls

make_mat(7)
>>>[[1, 2, 4, 8, 4, 2, 1],
[2, 4, 8, 16, 8, 4, 2],
[4, 8, 16, 32, 16, 8, 4],
[8, 16, 32, 64, 32, 16, 8],
[4, 8, 16, 32, 16, 8, 4],
[2, 4, 8, 16, 8, 4, 2],
[1, 2, 4, 8, 4, 2, 1]]

2、方法二:用map()和lambda将方法一简化
源码如下:

def make_mat(n):
return [[1<<sum(map(lambda x:int((n-1)/2-abs(x-(n-1)/2)),(i,j))) \
for j in range(n)]
2a81e
for i in range(n)]
make_mat(7)
>>>[[1, 2, 4, 8, 4, 2, 1],
[2, 4, 8, 16, 8, 4, 2],
[4, 8, 16, 32, 16, 8, 4],
[8, 16, 32, 64, 32, 16, 8],
[4, 8, 16, 32, 16, 8, 4],
[2, 4, 8, 16, 8, 4, 2],
[1, 2, 4, 8, 4, 2, 1]]

拆分理解如下:
abs( )表示求绝对值,即求 x-(n-1)/2 的绝对值,以绝对值的形式,可以实现方法一中判断是应该乘以还是除以2的功能。
lambda函数的功能是,对于每一个x,求 int((n-1)/2-abs(x-(n-1)/2)的值。

lambda x:int((n-1)/2-abs(x-(n-1)/2))

map( )可以对(i,j)这个数组的每个元素进行lambda操作,也就是对i和j分别进行lambda操作,返回的是迭代器,不能直接输出。

map(lambda x:int((n-1)/2-abs(x-(n-1)/2)),(i,j))

加上sum( )后,功能是在map返回的迭代器中每个数进行相乘,其等价于sum(list(map()))。

for j in range(n) 和for i in range(n)限定了循环的范围。

3、方法三:用传统的函数方法,不使用二进制
其实这个方法是我在没看到标准答案时候写出来的,相比标准答案实在有些繁琐,不过也放上来吧,不知道二进制位移和map函数的朋友,可能可以先从我这个思路入手:根据给定的n,先生成第一个子列表,再对第一个子列表进行操作生成后续的子列表。

源码如下:

import numpy as np

def get_first(n):   #根据n得到第一个子列表
list_o = []
num = 1
list_o.append(num)
for i in range(int((n+1)/2) -1):
num = num * 2
list_o.append(num)
#生成递增的那部分元素,并添加到列表中
for i in range(int(n/2)-1,-1,-1):
list_o.append(list_o[i])
#生成递减的那部分元素,并添加到列表中
return list_o

def get_all(ls,n,out):
a = np.array(ls)
#把列表转换为array数组,方便用每个元素乘以或除以2
out.append(list(a.astype(np.int16)))
#array数组默认是浮点数,用array.astype(np.int16)转换为整数
for i in range(int((n+1)/2) -1):
#原理和获取第一个子列表是一样的。
a = a *2
#print(a)
out.append(list(a.astype(np.int16)))
for i in range(int(n/2)-1,-1,-1):
out.append(out[i])
return out

def make_mat(n):
n = n
out = []
print(get_all(get_first(n),n,out))

make_mat(7)
>>>[[1, 2, 4, 8, 4, 2, 1],
[2, 4, 8, 16, 8, 4, 2],
[4, 8, 16, 32, 16, 8, 4],
[8, 16, 32, 64, 32, 16, 8],
[4, 8, 16, 32, 16, 8, 4],
[2, 4, 8, 16, 8, 4, 2],
[1, 2, 4, 8, 4, 2, 1]]

为了改进用户体验,添加了获取输入和输出的提示词以及捕捉异常,将主函数改成如下代码:

def make_mat():
while True:
get_num = input("请输入n的值,n为正整数(按e结束进程):")
try:
if get_num == "e":
break
elif isinstance (eval(get_num),int) and (eval(get_num)>1):
n = eval(get_num)
out = []
print("得到的结果是:\n{}".format(get_all(get_first(n),n,out)))
elif get_num == "1":
out = [[1]]
print("得到的结果是:\n{}".format(out))
else:
print("请输入正确的n值。")
except:
print("请输入正确的n值。")

其中 isinstance (x,A)是对x进行类型判断,如果x属于A类型,则返回True,否则返回False。

>>> isinstance(121,int)
True
>>> isinstance(123,str)
False

写在最后:

推荐一个画NS图的工具,DiagramDesignerSetup1.28,修改方便,简单易学。
中文版下载 http://pan.baidu.com/s/1eSsFURS

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: