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

    xiaoxiao2023-12-28  174

    一、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)]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

    最新回复(0)