Python学习之路——列表语法练习

Python习题练习

  • 0.前言
  • 1.列表练习
    • 1.1.已知一个列表,求所有元素和
    • 1.2.已知一个列表,输出所有奇数下标元素。list = [1,2,3,4,5,6,7]
    • 1.3.已知一个列表,将所有元素乘二。list = [1,2,3,4,5,6]
    • 1.4把1----36分别放入6x6列表中,计算列表数组对角元素之和
    • 1.5.有一个长度是10的列表列表内有10个不重复的数字,要求按从大到小排序。list =[1,3,34,32,98,74,92,83,23,124]
    • 1.6有一个长度是10的列表,要求删除第6个元素。list = [1,3,34,32,98,74,92,83,23,124]
    • 1.7有一个长度是10的列表,按递增排列,用户输入一个数,插入适当位置。list = [1,10,100,200,201,202,233,345]
    • 1.8有一个长度是10的列表,列表内有10个人名,要求去掉重复的。list = ['jack','uzi','kangkang','condi','rose','fizz','condi','uzi'],
    • 1.9求1~100之间能被7整除,但不能同时被5整除的所有整数
  • 2.Q&A
    • 2.1.Q:弱类型和强类型的区别是啥?
  • 3.总结

0.前言

在学了一部分Python的基础语法之后,深刻的意识到"talk is cheap, show me your code",做了一些习题,挑选了一部分我个人有所些心得的如下。

1.列表练习

1.1.已知一个列表,求所有元素和

先分析一下,常规思维是不是,遍历这个列表,然后设置一下sum的变量存放相加之后的值。如果是学的是Java我肯定会这样做(实际上最开始我确实是这样做的),后来得知了Python内置有sum()函数,括号里的需要求和的列表。所以代码可以这样写

l = list(range(1, 100)) #生成一个列表
print(sum(l))

这样是不是相当简洁,很符合Python之禅里的Simple is better than complex

1.2.已知一个列表,输出所有奇数下标元素。list = [1,2,3,4,5,6,7]

按照传统的思维,遍历根据下标是否能否能整除2,输出符合条件的元素。但这里是Python啊。Python列表中有一个很重要的功能就是切片。

格式为list[a: b :c],这段话的意思是在下标[a,b)的范围内,每间隔c个位置,取1个元素,最后把这些元素组成一个新的列表。注意范围是前开后闭(在程序语言中大多数是这样的),a缺省代表从第一个(下标0)b缺省代表到最后一个,c缺省代表间隔为1。-1代表的是最后一个元素。这里需要注意的是如果写的是0,表示的是从原列表中的第一个到倒数第二个元素组成的列表,因为是前开后闭。顺着这个思路,代码如下:

list = [1, 2, 3, 4, 5, 6, 7]
list2 = list[1::2] #从下标1到最后一个,间隔为2
print(list2)

1.3.已知一个列表,将所有元素乘二。list = [1,2,3,4,5,6]

常规思路,遍历之后乘2,再重新赋值给当前位置的元素。Python可以使用列表推导式
[表达式 for 变量 in 列表] 这个是标准的格式。看例子来理解,这个题的代码如下:

list_a = [1, 2, 3, 4, 5, 6, 7]
list_a = [2 * i for i in list_a] #表达式为2*i,i 代表的是list_a中的单个元素
print(list_a)

这只是一个简单的列表推导式。列表推导式在Python中用处很大,可以大大减少代码量,而且可读性也不错。但不太建议为了追求这种字面上的简洁,使用很复杂的列表推导式。原因就是不管怎么说,这种列表推导式还是不符合常人逻辑的,像这种比较简单的还好,一旦遇到复杂的,比如后面的某道题,还是有点让人费解,需要想一会才明白。毕竟代码不是自嗨的,是需要和他人合作的,如果你写的代码让人看不懂,证明不了你有多厉害,反而让人觉得你很蠢。

1.4把1----36分别放入6x6列表中,计算列表数组对角元素之和

在所有列表的题中,这题是唯一一个费了我一些时间的题目。这题的解法没什么新颖的,主要是一点。如何创建一个二维列表,这里又用到了列表推导式,先放代码。

l = [[] for i in range(6)]#生成一个二维列表
for i in range(1, 7):
    for j in range(1, 7):
        l[i - 1].append(6 * i + j - 6)
print(l)

这个代码好好想想都能懂。我们分析一个生成二维列表的这个代码,如果不执行下面的操作,只对这个l输入,结果为:[[], [], [], [], [], []]。这题像不像是把列表推导式中的表达式复制了6遍?即把i依次代入,表达式得出结果,即使不是range,其它元素个数为6的列表都可以生成这样的结果。这样你对列表表达式是不是有更深的理解了?
Python学习之路——列表语法练习_第1张图片

1.5.有一个长度是10的列表列表内有10个不重复的数字,要求按从大到小排序。list =[1,3,34,32,98,74,92,83,23,124]

这题也简单,就是介绍一下,Python自带的有一个sort()方法,可以对列表排序(a.sort()),不过默认的升序(绝大多数的排序默认就是升序),如果想要降序,只需要在sort()括号里面加入,reverse=True,表示按照降序排序(reverse默认值为False,即为升序)。代码如下:

list =[1,3,34,32,98,74,92,83,23,124]
list.sort(reverse=True)
print(list)

其中这个参数还可以加入排序依照的关键词key,这个用法就很多了,我也是初学者不太熟练,想了解的就自己查一下资料吧。Python除了sort()方法还有一个sorted(),区别在于一个是对原有序列操作,一个是新生成一个序列,比如a.sort(),而b=sorted(a)。

1.6有一个长度是10的列表,要求删除第6个元素。list = [1,3,34,32,98,74,92,83,23,124]

这题也简单,主要是说明一下列表中移除元素的几个方法。代码如下:

list = [1,3,34,32,98,74,92,83,23,124]
del list[5]
print(list)

del list[i]表示的是删除列表中下标为i的元素,无返回值

list.remove(object)表示的是删除某一个特定的元素object,返回的是删除后object之后的列表

list.pop(i)表示的是删除下标为i的元素,返回值是删除掉的值,如果i缺省,默认从最后一个开始删

除,这个pop()方法对于学过数据结构的都知道。所以最开始我用Python的while遍历列表的时候都是用list.pop()是否为空确定是否完全遍历。

1.7有一个长度是10的列表,按递增排列,用户输入一个数,插入适当位置。list = [1,10,100,200,201,202,233,345]

这个题乍一看挺容易的,一个insert()足以。但我们仔细一想,要按照递增的序列。偷懒一点的,可以直接append()在列表最后,然后再排序,但这个题显然不是考我们这个。我们需要保证这个数插入之后,列表还是递增的。代码如下:

#def表示定义一个函数/方法,insert_method,表示方法名,o和l表示参数。
def insert_method(o, l):# 使用冒号表示方法体
    l = list(l)()#必须进行这一步操作,不然使用不了list的方法
    for i in l:# 对列表循环
        if o < i:# 判断的大小
            l.insert(l.index(i), o)# 如果大于就把o插入到当前元素的位置,其后的元素都会自动后移
            return l#返回添加之后的列表,l.insert()无返回值,只代表对l操作
    #如果o大于l中的所有元素,就把o拼接在l的最后面,而且l.append()方法无返回值
    l.append(o)
    return l

li = [1, 10, 100, 200, 201, 202, 233, 345]
print(insert_method(500, li))

需要特别说明的几点
Python中的变量名分割使用_分割而且一般不使用大写字母,这点和Java的驼峰式命名不一样。

必须要进行list(l)的操作才能让编译器知道,你这是在对list操作,才可以使用list的方法,这就是Python作为弱类型语言的一个缺点吧,文末会有我个人对强类型和弱类型的一些理解。

因为insert()和append()无返回值,也就是说不能直接 return l.append(o),否则会返回None(等于Java中的null)表示空值。

1.8有一个长度是10的列表,列表内有10个人名,要求去掉重复的。list = [‘jack’,‘uzi’,‘kangkang’,‘condi’,‘rose’,‘fizz’,‘condi’,‘uzi’],

这题很有意思,常规做法,遍历每个值把它与其余的值对比,遇到重复的就删除其余值中的那个。和选择排序有点像,这个一点都不Python。进阶一点的做法,建立一个空列表,把原列表的值依次放入新列表中,然后利用not in新列表来判断人名是否在新列表中出现过,这个有点Python的样子了,代码如下:

l = ['jack', 'uzi', 'kangkang', 'condi', 'rose', 'fizz', 'condi', 'uzi']
l2 = []
for i in l:
    if i not in l2:
        l2.append(i)
print(l2)

但这个也不是最Python的做法,我们想一下,Python中的基本元素有哪个是无重复值的——集合(set),集合默认是无重复值的(和数学中的集合定义是不是一样呢),我们只需要把列表转换成集合,然后再把集合转成列表即可,代码如下:

l = ['jack', 'uzi', 'kangkang', 'condi', 'rose', 'fizz', 'condi', 'uzi']
l = list(set(l))# 先转成集合,再转成列表
print(l)

仔细观察结果,发现是不是列表元素的顺序变了?对,这是这个方法的缺点,会打乱原列表的顺序。
Python学习之路——列表语法练习_第2张图片
解决方法也是有,但这样的解决方法有点脱裤子放屁的感觉,使用之后失去了Python的感觉,还是代码如下:

l = ['jack', 'uzi', 'kangkang', 'condi', 'rose', 'fizz', 'condi', 'uzi']
s = set(l)
l2 = list(s).sort(key=l.index)# key代表的是排序关键字,即以l的下标为排序的关键字
print(l)

这里说一下这个l.index,注意没有(),也就是说这个不是一个方法,如果把它打印出来,它返回的是一个物理地址

<built-in method index of list object at 0x0000021E43F20800>

以我的理解来看,我觉得是因为l这个列表中的每一个元素在内存中的地址是有顺序的,Python是基于值管理变量的,同一个值得变量在内存中的地址一般是同一个,那么按照这个物理地址的顺序,可以把这些元素按照原列表的顺序排出来。可能理解的还不透彻。

1.9求1~100之间能被7整除,但不能同时被5整除的所有整数

这道题不难,主要是为了向大家说明一个问题,代码如下:

for j in [i for i in range(1, 101) if (i % 7 == 0 and i % 5 != 0)]:
    print(j, end=",")

一看,直接两行解决,多简洁,多Python,多好。但我们仔细深究一下,一味的追求简洁有意义吗?且不说编辑器一次能看这么长的问题,这么长的代码,人光分析就得好一会,才明白。如果起那么的i是个复杂的表达式,后面的if条件再多一点,乍一看肯定懵,而且写这么长也容易出错。而Python作为弱类型语言,很多错误都是只能在运行出来之后排查,如果你的代码都是这样,那么排查起来也比较困难。这就是我觉得不要使用太复杂的条件表达式的原因。

2.Q&A

2.1.Q:弱类型和强类型的区别是啥?

A:这个问题之前我也不知道,只是听说过Java是强类型,Python是弱类型,但怎么区分和为什么要有强类型,为什么要有弱类型这个问题只到我自己用过Python以及看到一些说法之后才懂。把个人愚见表达于此。

看上文中的1.7,如果我在insert_method中写入return l.insert(l.index(i), o)或者return l.append(o),编译器不会报错,因为方法体没指定返回的变量类型,如果这样写得到的print出的值是None。但在Java中编译器会提前报错,因为我会在方法体声明的时候指定返回类型为list。下面举一个实际开发的例子。
所谓强类型,就是变量声明时,必须指定变量类型,比如 在Java中Teacher Tony=new Teacher()这样我就知道了Tony是个老师,假设他有一个方法teach(),在Python中Tony=xx(暂时还没学到Python的面向对象,所以用xx代替),Python中这个Tony是啥,在运行结果出来之前,我不知道它是啥,它可以代表老师也可以代表学生,通过运行出来的结果,看它所表现的特点才可以知道,Tony是人啊。如果我要表达Tony教学生Jack,在Java中,Tony.teach(Jack),如果我写成了Jack.teach(Tony),因为Jack是学生,没有teach方法,所以编译器不会通过。但Python中,如果写成了Jack.teach.(Tony)编译器不会报错,直到运行出来的结果不对才能去找问题。

但弱类型就没有优点了吗?弱类型代码量比较少,开发起来比较快,适合小型项目。毕竟可以随意转换类型,自由度高,但都知道一句歌词是我给你自由过了火,让你更寂寞,才会陷入感情漩涡自由度过高就是容易导致由于标准不统一,而且不是每个人的代码易读性都很高,可能过不了几天自己都不知道写的是啥了,协作开发会更麻烦。一个好消息是,强类型语言都已经支持弱语言类型了,比如Java的var,弱类型的也开始支持强类型的,比如l2=list(l),所以只能说二者各有优劣,不能说谁比谁好。

我的这个解释或许不全面,但是目前我这个阶段的理解,也算是能说的通。

3.总结

通过这次实践,我初步掌握了Python列表的基本上使用和一些小技巧。我也深刻的理解了Python和Java的优缺点,虽然Java冗长,但正是因为这些看似多余的代码,保证了Java的严谨和统一性,不容易写错,适合大型项目。而Python虽然简洁明了,但自由度较高,容易写出一些可读性不高的代码,适合小型项目。

你可能感兴趣的:(Python,列表,python,java)