Python学习日记06

Day.06

2020.02.24
今天主要学习的内容是字典以及函数和模块的使用。
在这之前首先要说一个python中比较基础的问题:if name == 'main’语句的使用。
用一句话来概括:这个语句是用来防止导入时调用未被封装的主函数。具体内容可以参考以下文章:
python中为什么需要使用“if name == ‘main’”语句

1.字典

字典和列表相似,也是可以进行元素值的修改,但是最大的不同是,字典中访问元素是通过键来访问的,而列表和元组都是通过下标访问。我个人的理解就是,字典中的键对应的就是列表元组中的下标,字典中的值对应的就是列表元组中相应的元素,和前两种变量类型相比,字典的方便之处就在于可以不用考虑下标顺序索引元素值。
同样的,字典也有修改、删除的方法。
修改的话直接对已有的键赋新值即可,如果对原字典中没有出现过的键赋值,则默认是添加一个新的键/值对。
删除操作可以用del,也可以用clear。两者的区别在于,del可以删除单个值,或者删除整个字典,删除之后再进行访问字典操作是会报错的,而clear的作用是清空字典,执行完之后剩下的是一个空字典。
和列表元组类似,字典中也内置了相应的函数和方法(这里省略了示例,因为太长了):

函数&方法描述
len(dict)计算字典元素个数,即键的总数
str(dict)输出字典,以可打印的字符串表示
type(variable)返回输入的变量类型,如果变量是字典就返回字典类型
radiansdict.clear()删除字典内所有元素
radiansdict.copy()返回一个字典的浅复制
radiansdict.fromkeys()创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值
radiansdict.get(key, default=None)返回指定键的值,如果值不在字典中返回default值
key in dict如果键在字典dict里返回true,否则返回false
radiansdict.items()以列表返回可遍历的(键,值)元组数组
radiansdict.keys()返回一个迭代器,可以使用list()来转换为列表
radiansdict.setdefault(key, default=None)和get()类似,但如果键不存在于字典中,将会添加键并将值设为default
radiansdict.update(dict2)把字典dict2的键/值对更新到dict里
radiansdict.values()返回一个迭代器,可以使用list()来转换为列表
pop(key[,default])删除字典给定键key所对应的值,返回值为被删除的值。key值必须给出。否则,返回default值
popitem()随机返回并删除字典中的最后一对键和值

相应的字典练习题:

#练习题1:创建一个名为favorite_places的字典
#在这个字典中,将三个人的名字用作键;对于其中的每个人,都存储他喜欢的1〜3个地方
#具体实现方法:
favourite_places = {'张三': ['西湖', '灵隐寺'], '李四': ['颐和园', '故宫'], '王五': ['洞庭湖', '钱塘江']}
print(favourite_places)
#测试结果:
#{'张三': ['西湖', '灵隐寺'], '李四': ['颐和园', '故宫'], '王五': ['洞庭湖', '钱塘江']}

小结:一键多值的方法很简单,每个键对应一个列表即可,而列表里是可以存放很多值的。

#练习题2:创建多个字典,对于每个字典,都使用一个宠物的名称来给给它命名;
#在每个字典中,包含宠物的类型及其主人的名字
#将这这些字典存储在一个名为pets的列表中,再遍历该列表,并将宠物的所有信息都打印出来
#具体实现方法:
pet1 = {'type': '猫', 'master': '张三'}
pet2 = {'type': '狗', 'master': '李四'}
pet3 = {'type': '狗', 'master': '王五'}
pets = [pet1, pet2, pet3]
print(pets)
#测试结果:
#[{'type': '猫', 'master': '张三'}, {'type': '狗', 'master': '李四'}, {'type': '狗', 'master': '王五'}]

小结:和上一题的字典中包含列表作对比,这一题是列表中包含字典。在实际使用过程中当然是哪种方便用哪种,但是要注意的一点是,在字典中,值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组,列表不可以作为字典的键来使用。

2.函数和模块的使用

学过一些语言知识的同学应该都清楚,计算机语言中的函数最大的作用就是解决重复代码的问题。将所要重复编写的代码封装进一个函数中,需要用到时再调用,不仅可以让代码更加简洁、可读性更高,更方便了自己,减少自己的工作量。
python中函数的定义也和C++类似,不过C++需要定义返回值的类型,而python不用。在python中,使用def xxx()来定义一个函数,xxx是函数名,()中填入需要传递的参数,函数最后也需要一个return来返回值(也可以不写,默认返回none),因为我有过语言基础,所以不多作阐述。
此外,因为python的函数参数可以有默认值,也支持使用可变参数,所以不需要函数的重载。其中使用可变参数的方法是在参数前加*号。当在不同模块中想要避免同名函数的冲突时,可以使用from…import…或者import…as…,当然,如果使用from…import…语句的话,后面导入的那个函数会覆盖之前的那个函数,所以个人认为还是使用import…as…来指定一个名字,通过点号.调用该模块的函数比较清晰。
还有需要注意的一点在今日文章的最开头已经讲到了,每个模块其实就是用户自己写的一个.py文件,当中除了定义的函数以外,肯定还存在着可执行代码(也就是在函数体之外未被封装的那一部分),那么为了防止其他程序员调用该模块时执行了未被封装的那部分代码,就需要将这部分代码写在if name == ‘main’语句下面。这和C++中的.h头文件和.cpp源文件是不同的。
下面通过具体实例来练习函数和模块的使用:

#练习题1:实现计算求最大公约数和最小公倍数的函数
#具体实现方法:
def calculate(num1, num2):
    beichushu = num1
    chushu = num2
    yushu = beichushu % chushu
    while 1:
        if yushu == 0:
            print('%d和%d的最大公约数是:%d' % (num1, num2, chushu))
            print('%d和%d的最小公倍数是:%d' % (num1, num2, (num1*num2)/chushu))
            break
        else:
            beichushu = chushu
            chushu = yushu
            yushu = beichushu % chushu


if __name__ == '__main__':
    while 1:
        print('请输入两个正整数:')
        a = int(input('请输入第一个数:'))
        b = int(input('请输入另一个数:'))
        calculate(a, b)
#测试结果:
#请输入两个正整数:
#请输入第一个数:2
#请输入另一个数:6
#2和6的最大公约数是:2
#2和6的最小公倍数是:6
#请输入两个正整数:
#请输入第一个数:36
#请输入另一个数:270
#36和270的最大公约数是:18
#36和270的最小公倍数是:540
#请输入两个正整数:
#请输入第一个数:18
#请输入另一个数:20
#18和20的最大公约数是:2
#18和20的最小公倍数是:180
#请输入两个正整数:
#请输入第一个数:
#Process finished with exit code -1

小结:实现最大公约数和最小公倍数的方法这里不过多阐述,第四天的日记已经具体解释。这题主要就是练习函数封装和调用的过程,此外,还有一个收获就是PyCharm还会很好心地纠正格式错误:在函数体上下都要空两行。

#练习题2:实现判断一个数是不是回文数的函数
#具体实现方法:
def judge(x):
    y = []
    y += x
    x.reverse()
    if x == y:
        print('是回文数')
    else:
        print('不是回文数')


if __name__ == '__main__':
    while 1:
        a = list(input('请输入一个数:'))
        judge(a)
#测试结果:
#请输入一个数:123456
#不是回文数
#请输入一个数:12321
#是回文数
#请输入一个数:1221
#是回文数
#请输入一个数:123210
#不是回文数
#请输入一个数:1234321
#是回文数
#请输入一个数:12344321
#是回文数
#请输入一个数:
#Process finished with exit code -1

小结:判断回文数我在这里还是选择通过列表实现,因为列表本身自带一个reverse()函数,只要判断反转之后是否和原来的列表相等即可。但是在具体操作的过程中,碰到了两个问题:①列表本身自带的reverse()函数的返回值是none,所以print(x.reverse())还是x == x.reverse(),其结果都是false;②python中的等号=赋值和C++中的赋值有所区别,因为python是动态语言,所以在python中,任何变量存放的都是对象(真正数据)的引用(类似于C的指针,但还是有区别的)。基于这个原理,如果先将列表x赋值给一个新变量y,再将列表x反转的话,那么y也会跟着反转。解决这个问题的方法就是:创建两个列表——先创建一个空列表y,再让y连接上x的列表,这个时候,我们所用的其实是两个列表,只不过他们俩元素完全相同而已,而如果直接y = x的话,其实本质上只有一个列表。
想要更清楚地了解这个问题可以查看知乎上的以下内容:
为什么python中将列表1赋值给列表2后将列表2顺序反转也会影响列表1?

#练习题3:实现判断一个数是不是素数的函数
#具体实现方法:
def judge(x):
    count = 0
    for y in range(1, x+1):
        if x % y == 0:
            count += 1
    if count == 2:
        print('%d是素数' % x)
    else:
        print('%d不是素数' % x)


if __name__ == '__main__':
    while 1:
        a = int(input('请输入一个数:'))
        judge(a)
#测试结果:
#请输入一个数:2
#2是素数
#请输入一个数:3
#3是素数
#请输入一个数:4
#4不是素数
#请输入一个数:5
#5是素数
#请输入一个数:6
#6不是素数
#请输入一个数:7
#7是素数
#请输入一个数:
#Process finished with exit code -1

小结:素数算法已经是第三次碰到了,这里也不过多描述。这题还是比较基础的,没有什么太大的问题,只要将算法封装在函数中再在主体调用即可。

#练习题4:写一个程序判断输入的正整数是不是回文素数
#具体实现方法:
def judge(x):
    count = 0
    str1 = ''
    y = []
    y += x
    x.reverse()
    for n in range(len(y)):
        str1 += y[n]
    z = int(str1)
    for m in range(1, z+1):
        if z % m == 0:
            count += 1
    if x == y and count == 2 and z>=11:  #回文素数要求≥11的整数
        print('%d是回文素数' % z)
    else:
        print('%d不是回文素数' % z)


if __name__ == '__main__':
    while 1:
        num1 = list(input('请输入一个数:'))
        judge(num1)
#测试结果:
#请输入一个数:11
#11是回文素数
#请输入一个数:2
#2不是回文素数
#请输入一个数:5
#5不是回文素数
#请输入一个数:131
#131是回文素数
#请输入一个数:101
#101是回文素数
#请输入一个数:151
#151是回文素数
#请输入一个数:152
#152不是回文素数
#请输入一个数:
#Process finished with exit code -1

小结:这一题可以看做是上面两题的结合,但是具体操作还需要加入一点细节。总体思路和上面两题一致:判断是否回文,采用列表反转之后的新列表和原列表对比;判断是否是素数,采用计算约数个数的方法,两个约数则为素数。在实际编写的过程中,产生了多次错误,主要是列表和整数之间的转化。首先,列表是不能直接通过强制类型转换为整数的,只能用一个for循环将列表中的元素逐个输出,然后用一个空字符串把输出的列表元素拼接上去,成为一串内容和列表一样的字符串,再通过强制类型转换将其转为整数型。

3.今日总结

今天的练习题在具体算法上其实和前几天写的东西大致相似,主要是感受一下函数封装和调用的一个过程,这也是后面写大程序、大项目时所必须要会的一个技能。此外,在编写实例时遇到的问题也让我收获颇丰,比如,列表不能通过int()强制转换为整型,但是字符串却可以,这些细小的知识在参考书上是难以看到的,也是难以记忆的,只有通过自己不断的练习,去积累错误,才会有一个更深的印象,一个更深的理解。在阅读骆昊的github项目时,我也学到了全局变量的调用方式,只需要在变量前加global即可,但是,全局变量作用域太过广泛,还是不要经常调用比较好。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值