python 用if判断一个数是不是整数_Python基础教程07-函数和模块的使用

d87978306d7086497782a9f594641dce.png

在讲解本章节的内容之前,我们先来研究一道数学题,请说出下面的方程有多少组正整数解。

x1+x2+x3+x4=8

事实上,上面的问题等同于将8个苹果分成四组每组至少一个苹果有多少种方案。想到这一点问题的答案就呼之欲出了。

2ed70e0fd3d534107ac222a52fc834d6.png

可以用Python的程序来计算出这个值,代码如下所示。

"""输入M和N计算C(M,N)"""m = int(input('m = '))n = int(input('n = '))fm = 1for num in range(1, m + 1):    fm *= numfn = 1for num in range(1, n + 1):    fn *= numfmn = 1for num in range(1, m - n + 1):    fmn *= numprint(fm // fn // fmn)

函数的作用

不知道大家是否注意到,在上面的代码中,我们做了3次求阶乘,这样的代码实际上就是重复代码。编程大师Martin Fowler先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”,要写出高质量的代码首先要解决的就是重复代码的问题。对于上面的代码来说,我们可以将计算阶乘的功能封装到一个称之为“函数”的功能模块中,在需要计算阶乘的地方,我们只需要“调用”这个“函数”就可以了。

定义函数

在Python中可以使用def关键字来定义函数,和变量一样每个函数也有一个响亮的名字,而且命名规则跟变量的命名规则是一致的。在函数名后面的圆括号中可以放置传递给函数的参数,这一点和数学上的函数非常相似,程序中函数的参数就相当于是数学上说的函数的自变量,而函数执行完成后我们可以通过return关键字来返回一个值,这相当于数学上说的函数的因变量。

在了解了如何定义函数后,我们可以对上面的代码进行重构,所谓重构就是在不影响代码执行结果的前提下对代码的结构进行调整,重构之后的代码如下所示。

def factorial(num):    """求阶乘"""    result = 1    for n in range(1, num + 1):        result *= n    return resultm = int(input('m = '))n = int(input('n = '))# 当需要计算阶乘的时候不用再写循环求阶乘而是直接调用已经定义好的函数print(factorial(m) // factorial(n) // factorial(m - n))

说明: Python的math模块中其实已经有一个factorial函数了,事实上要计算阶乘可以直接使用这个现成的函数而不用自己定义。下面例子中的一些函数在Python中也都是现成的,我们这里是为了讲解函数的定义和使用才把它们又实现了一遍,实际开发中不建议做这种低级的重复性的工作。

函数的参数

函数是绝大多数编程语言中都支持的一个代码的"构建块",但是Python中的函数与其他语言中的函数还是有很多不太相同的地方,其中一个显著的区别就是Python对函数参数的处理。在Python中,函数的参数可以有默认值,也支持使用可变参数,所以Python并不需要像其他语言一样支持函数的重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式,下面是两个小例子。

from random import randintdef roll_dice(n=2):    """摇色子"""    total = 0    for _ in range(n):        total += randint(1, 6)    return totaldef add(a=0, b=0, c=0):    """三个数相加"""    return a + b + c# 如果没有指定参数那么使用默认值摇两颗色子print(roll_dice())# 摇三颗色子print(roll_dice(3))print(add())print(add(1))print(add(1, 2))print(add(1, 2, 3))# 传递参数时可以不按照设定的顺序进行传递print(add(c=50, a=100, b=200))

我们给上面两个函数的参数都设定了默认值,这也就意味着如果在调用函数的时候如果没有传入对应参数的值时将使用该参数的默认值,所以在上面的代码中我们可以用各种不同的方式去调用add函数,这跟其他很多语言中函数重载的效果是一致的。

其实上面的add函数还有更好的实现方案,因为我们可能会对0个或多个参数进行加法运算,而具体有多少个参数是由调用者来决定,我们作为函数的设计者对这一点是一无所知的,因此在不确定参数个数的时候,我们可以使用可变参数,代码如下所示。

# 在参数名前面的*表示args是一个可变参数def add(*args):    total = 0    for val in args:        total += val    return total# 在调用add函数时可以传入0个或多个参数print(add())print(add(1))print(add(1, 2))print(add(1, 2, 3))print(add(1, 3, 5, 7, 9))

用模块管理函数

对于任何一种编程语言来说,给变量、函数这样的标识符起名字都是一个让人头疼的问题,因为我们会遇到命名冲突这种尴尬的情况。最简单的场景就是在同一个.py文件中定义了两个同名函数,由于Python没有函数重载的概念,那么后面的定义会覆盖之前的定义,也就意味着两个函数同名函数实际上只有一个是存在的。

def foo():    print('hello, world!')def foo():    print('goodbye, world!')# 下面的代码会输出什么呢?foo()

当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为foo的函数,那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过import关键字导入指定的模块就可以区分到底要使用的是哪个模块中的foo函数,代码如下所示。

module1.py

def foo():    print('hello, world!')

module2.py

def foo():    print('goodbye, world!')

test.py

from module1 import foo# 输出hello, world!foo()from module2 import foo# 输出goodbye, world!foo()

也可以按照如下所示的方式来区分到底要使用哪一个foo函数。

test.py

import module1 as m1import module2 as m2m1.foo()m2.foo()

但是如果将代码写成了下面的样子,那么程序中调用的是最后导入的那个foo,因为后导入的foo覆盖了之前导入的foo。

test.py

from module1 import foofrom module2 import foo# 输出goodbye, world!foo()

test.py

from module2 import foofrom module1 import foo# 输出hello, world!foo()

需要说明的是,如果我们导入的模块除了定义函数之外还中有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是"__main__"。

module3.py

def foo():    passdef bar():    pass# __name__是Python中一个隐含的变量它代表了模块的名字# 只有被Python解释器直接执行的模块的名字才是__main__if __name__ == '__main__':    print('call foo()')    foo()    print('call bar()')    bar()

test.py

import module3# 导入module3时 不会执行模块中if条件成立时的代码 因为模块的名字是module3而不是__main__

练习

练习1:实现计算求最大公约数和最小公倍数的函数。

参考答案:

def gcd(x, y):    """求最大公约数"""    (x, y) = (y, x) if x > y else (x, y)    for factor in range(x, 0, -1):        if x % factor == 0 and y % factor == 0:            return factordef lcm(x, y):    """求最小公倍数"""    return x * y // gcd(x, y)

练习2:实现判断一个数是不是回文数的函数。

参考答案:

def is_palindrome(num):    """判断一个数是不是回文数"""    temp = num    total = 0    while temp > 0:        total = total * 10 + temp % 10        temp //= 10    return total == num

练习3:实现判断一个数是不是素数的函数。

参考答案:

def is_prime(num):    """判断一个数是不是素数"""    for factor in range(2, num):        if num % factor == 0:            return False    return True if num != 1 else False

练习4:写一个程序判断输入的正整数是不是回文素数。

参考答案:

if __name__ == '__main__':    num = int(input('请输入正整数: '))    if is_palindrome(num) and is_prime(num):        print('%d是回文素数' % num)

注意:通过上面的程序可以看出,当我们将代码中重复出现的和相对独立的功能抽取成函数后,我们可以组合使用这些函数来解决更为复杂的问题,这也是我们为什么要定义和使用函数的一个非常重要的原因。

最后,我们来讨论一下Python中有关变量作用域的问题。

def foo():    b = 'hello'    # Python中可以在函数内部再定义函数    def bar():        c = True        print(a)        print(b)        print(c)    bar()    # print(c)  # NameError: name 'c' is not definedif __name__ == '__main__':    a = 100    # print(b)  # NameError: name 'b' is not defined    foo()

上面的代码能够顺利的执行并且打印出100、hello和True,但我们注意到了,在bar函数的内部并没有定义a和b两个变量,那么a和b是从哪里来的。我们在上面代码的if分支中定义了一个变量a,这是一个全局变量(global variable),属于全局作用域,因为它没有定义在任何一个函数中。在上面的foo函数中我们定义了变量b,这是一个定义在函数中的局部变量(local variable),属于局部作用域,在foo函数的外部并不能访问到它;但对于foo函数内部的bar函数来说,变量b属于嵌套作用域,在bar函数中我们是可以访问到它的。bar函数中的变量c属于局部作用域,在bar函数之外是无法访问的。事实上,Python查找一个变量时会按照“局部作用域”、“嵌套作用域”、“全局作用域”和“内置作用域”的顺序进行搜索,前三者我们在上面的代码中已经看到了,所谓的“内置作用域”就是Python内置的那些标识符,我们之前用过的input、print、int等都属于内置作用域。

再看看下面这段代码,我们希望通过函数调用修改全局变量a的值,但实际上下面的代码是做不到的。

def foo():    a = 200    print(a)  # 200if __name__ == '__main__':    a = 100    foo()    print(a)  # 100

在调用foo函数后,我们发现a的值仍然是100,这是因为当我们在函数foo中写a = 200的时候,是重新定义了一个名字为a的局部变量,它跟全局作用域的a并不是同一个变量,因为局部作用域中有了自己的变量a,因此foo函数不再搜索全局作用域中的a。如果我们希望在foo函数中修改全局作用域中的a,代码如下所示。

def foo():    global a    a = 200    print(a)  # 200if __name__ == '__main__':    a = 100    foo()    print(a)  # 200

我们可以使用global关键字来指示foo函数中的变量a来自于全局作用域,如果全局作用域中没有a,那么下面一行的代码就会定义变量a并将其置于全局作用域。同理,如果我们希望函数内部的函数能够修改嵌套作用域中的变量,可以使用nonlocal关键字来指示变量来自于嵌套作用域,请大家自行试验。

在实际开发中,我们应该尽量减少对全局变量的使用,因为全局变量的作用域和影响过于广泛,可能会发生意料之外的修改和使用,除此之外全局变量比局部变量拥有更长的生命周期,可能导致对象占用的内存长时间无法被垃圾回收。事实上,减少对全局变量的使用,也是降低代码之间耦合度的一个重要举措,同时也是对迪米特法则的践行。减少全局变量的使用就意味着我们应该尽量让变量的作用域在函数的内部,但是如果我们希望将一个局部变量的生命周期延长,使其在定义它的函数调用结束后依然可以使用它的值,这时候就需要使用闭包,这个我们在后续的内容中进行讲解。

说明: 很多人经常会将“闭包”和“匿名函数”混为一谈,但实际上它们并不是一回事,如果想了解这个概念,可以看看维基百科的解释或者知乎上对这个概念的讨论。

说了那么多,其实结论很简单,从现在开始我们可以将Python代码按照下面的格式进行书写,这一点点的改进其实就是在我们理解了函数和作用域的基础上跨出的巨大的一步。

def main():    # Todo: Add your code here    passif __name__ == '__main__':    main()

欢迎关注~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/502372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端跨域请求get_(单点登录)跨域SSO看这篇文章就够了:前端篇

前言前俩篇文章,我们从概念,聊到了服务器中设计的内容。不知道大家是否觉得通俗易懂呢?接下来的内容则有些偏向前端部分。正文三、Cookie传递3.1、通过URL参数实现跨域信息传递我们要在A域实现写入token到B域,需要在A域设计一个se…

win10 如何锁定计算机,Win10 1909 专业版怎么锁定计算机屏幕

Win10 1909 专业版怎么锁定计算机屏幕?如果我们需要暂时离开计算机,但不想关机或者注销当前登录,那么为了防止未经授权的使用,我们可以将计算机锁定。在本文中,win10之家小编给大家分享如何自动锁定Windows 10计算机。Win10 1909…

qfile指定从多少行开始_大牛进化路上之Linux基础命令,看看你了解多少?

玩转Linux系统还是要从基础命令开始,基础命令是你大牛发展之路的第一步,扎实的基本命令操作功底才能在工作中游刃有余,下面我们就来看看吧。路径切换说明Linux中分绝对路径和相对路径,绝对路径一定是从/开始写的,还可能…

如何开机进入grub界面_如何进入http://192.168.1.1的设置界面 ?

登入192.168.1.1管理界面需要确保前期的硬件连接和已获知路由器的账号密码。接下来详细介绍:1、首先做好准备,检查一下是否已经连接好无线路由器和网线、调制解调器,要确保网络畅通、所有指示灯都正常亮着;2、然后打开手机设置&am…

手机html5雪花飘落,如何使用HTML5canvas实现雪花飘落

这篇文章主要为大家详细介绍了HTML5 canvas实现雪花飘落特效,效果实现引人入胜,很逼真的动画效果,感兴趣的小伙伴们可以参考一下看到网上很多展示html5雪花飞动的效果,确实非常引人入胜,我相信大家也跟我一样看着心动的…

灰度调节_网关实现灰度发布

一、背景互联网产品开发有个非常特别的地方,就是不停的升级,升级,再升级。采用敏捷开发的方式,基本上保持每周或者每两周一次的发布频率,系统升级总是伴随着各种风险,新旧版本兼容的风险,用户使…

string类的erase函数属于stl吗_探索STL容器:vector

用了这么久的 vector ,今天终于有时间来看下STL的实现源码了,开心?~最近几个月在刷 leetcode ,用的较多的数据结构就是STL里面的 vector 了,相比较于直接的 array 数组,它具备了灵活地根据需求去分配管理内存&#xf…

泰森怎么会输给道格拉斯_泰森24岁就被击败,如果能像他学习巅峰时期至少能延长三年...

一个职业拳击手的运动生涯长短,除了与自身的打法风格有关外,最重要的就是自律,有很多拳手自身天赋极高,但当他成名之后,随着金钱和荣誉的到来往往无法把持自己,最终走向衰退。我们都知道,拳王迈…

数字加密c语言程序_国外程序员整理的 C++ 资源大全

喜欢的话可以收藏转发加关注摘要:C是在C语言的基础上开发的一种集面向对象编程、泛型编程和过程化编程于一体的编程语言。应用较为广泛,是一种静态数据类型检查的,支持多重编程的通用程序设计语言。关于 C 框架、库和资源的一些汇总列表&…

linux操作命令 mongo_Linux安装mongodb总结(仅学习)

原链接:Linux安装mongodb总结 - Lovebugs.cn - 博客园由于自己的博客上线部署时需要用到mongodb来存储图片文件,所以先在本地电脑上安装了mongodb做测试,由于之前没接触过mongodb,所以安装过程中遇到了各种小问题,折腾…

计算机二级必备快捷键知识,计算机二级考试中的一些注意事项️

原标题:计算机二级考试中的一些注意事项️科教武汉 【计算机二级考试中的一些注意事项️】1、要合理安排做题时间可以先通过观察整个题目的题形,判断整个试卷的难点,通过观察题型然后确定自己的应对策。选择题建议用时15-20分钟为好。自己要有…

vba 自定义function返回值_用vba解决excel如何求前面连续为0的个数

领导布置了任务,要求每天统计当月的发展量,并且统计有多少业务员最多连续多少天发展为0的情况,统计的表格是这样的。用几行简单的VBA语言就能解决这个问题首先打开vba编辑窗口,点击开发工具——visual basic(如果没有这个菜单&…

禁用计算机组策略和管理,计算机正在使用时,禁用或关闭组策略刷新 | MOS86

点击此处修复Windows错误并提高系统性能Group Policy(Windows 2000中引入的管理工具)可以确定组织中的用户和计算机的程序,网络资源和操作系统的运行方式。组策略可帮助用户通过在Windows Windows注册表中进行修改来为活动对象添加策略。通常,默认情况下…

怎么捡自己空投_使命召唤手游空投怎么快速找到?使命召唤手游快速找到空投技巧...

使命召唤手游怎么快速寻找空投?空投里面有高级武器跟护甲还有补给品,拿到空投你的装备就会比别人高几个档次。高手拿到空投后吃鸡概率大大提高。下面就为大家详细的介绍一下如何让你快速的找到空投。首先刚开始游戏的时候是不会出现空投的,一…

ubuntu rpm安装_为什么说Ubuntu是一个值得尊敬的Linux发行版

Ubuntu用了好长时间了,最早接触的是RedHat,个人使用体验并不好,当时一直在想,为什么就没有一个更好用的Linux操作系统呢?别万年不变的Windows不行吗?(当时作为一个穷学生党,完全不想…

linux怎样自动检查link文件_怎样理解和识别 Linux 中的文件类型 | Linux 中国

众所周知,在 Linux 中一切皆为文件,包括硬盘和显卡等。在 Linux 中导航时,大部分的文件都是普通文件和目录文件。但是也有其他的类型,对应于 5 类不同的作用。因此,理解 Linux 中的文件类型在许多方面都是非常重要的。…

c++ map底层_深入浅出Redisredis底层数据结构(上)

来源:http://t.cn/AigEOwRE相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-value数据库。在《Redis设计与实现》这样描述:Redis 数据…

绝对布局优势_前瞻布局+尖端科技+雄厚资金 恒大解锁造车的“正确姿势”

新能源汽车行业风起云涌,在造车新势力们交相厮杀之时,恒大闪电般完成“新能源车全产业链布局”,占据了绝对先发优势。先人一步驶入快车道的恒大并未止步于此,5月30日,恒大又宣布拿下英国顶级轮毂电机企业protean&#…

山东省计算机考试无法报名,山东省2017年9月全国计算机等级考试报名事项公告...

根据教育部考试中心《关于做好2017年全国计算机等级考试工作的通知》(教试中心函〔2016〕237号)和《关于做好2017年9月全国计算机等级考试报名工作的通知》(鲁招考[2017]67号)要求,现将2017年9月我省全国计算机等级考试报名有关事项公告如下:一、 考试科…

laravel redis_thinkphp+redis实现秒杀,缓存等功能

秒杀是商城常见功能 phpredis是最常见的秒杀功能1,安装redis,根据自己的php版本安装对应的redis扩展首先查看phpinfo();php环境信息2,下载redishttps://windows.php.net/downloads/pecl/snaps/redis/ https://windows.php.net/downloads/pecl…