问答题
0. 你有听说过DRY吗?
答:DRY 是程序员们公认的指导原则:Don’t Repeat Yourself.
快快武装你的思维吧,拿起函数,不要再去重复拷贝一段代码了!
1. 都是重复一段代码,为什么我要使用函数(而不使用简单的拷贝黏贴)呢?
答:使用函数:
- 可以降低代码量(调用函数只需要一行,而拷贝黏贴需要N倍代码)
- 可以降低维护成本(函数只需修改def部分内容,而拷贝黏贴则需要每一处出现的地方都作修改)
- 使序更容易阅读(没有人会希望看到一个程序重复一万行“I love FishC.com”)
3*. 创建函数使用什么关键字,要注意什么?
答:使用“def”关键字,要注意函数名后边要加上小括号“()”,然后小括号后边是冒号“:”,然后缩进部分均属于函数体的内容,例如:
def MyFun():
# 我是函数体
# 我也是函数体
# 我们都属于函数 MyFun()
# 噢,我不属于 MyFun()函数的了
4*. 请问这个函数有多少个参数?
def MyFun((x, y), (a, b)):
return x * y - a * b
答:如果你回答两个,那么恭喜你错啦,答案是0,因为类似于这样的写法是错误的!
我们分析下,函数的参数需要的是变量,而这里你试图用“元祖”的形式来传递是不可行的。
我想你如果这么写,应该是要表达这么个意思:
>>> def MyFun(x, y):
return x[0] * x[1] - y[0] * y[1]
>>> MyFun((3, 4), (1, 2))
10
5*. 请问调用以下这个函数会打印什么内容?
>>> def hello():
print('Hello World!')
return
print('Welcome To FishC.com!')
答:会打印:
>>> hello()
Hello World!
因为当Python执行到return语句的时候,Python认为函数到此结束,需要返回了(尽管没有任何返回值)。
0. 请问以下哪个是形参哪个是实参?
def MyFun(x):
return x ** 3
y = 3
print(MyFun(y))
答:x是形式参数(形参),y是实际参数(实参)。
跟绝大部分编程语言一样,形参指的是函数创建和定义过程中小括号里的参数,而实参指的是函数在调用过程中传递进去的参数。
1. 函数文档和直接用“#”为函数写注释有什么不同?
答:给函数写文档是为了让别人可以更好的理解你的函数,所以这是一个好习惯:
>>> def MyFirstFunction(name):
'函数文档在函数定义的最开头部分,用不记名字符串表示'
print('I love FishC.com!')
我们看到在函数开头写下的字符串Ta是不会打印出来的,但Ta会作为函数的一部分存储起来,这个我们称之为函数文档字符串,Ta的功能跟注释是一样的。
函数的文档字符串可以按如下方式访问:
>>> MyFirstFunction.__doc__
'函数文档在函数定义的最开头部分,用不记名字符串表示'
另外,我们用help()来访问这个函数也可以看到这个文档字符串:
>>> help(MyFirstFunction)
Help on function MyFirstFunction in module __main__:
MyFirstFunction(name)
函数文档在函数定义的最开头部分,用不记名字符串表示
0*. 下边程序会输出什么?
def next():
print('我在next()函数里...')
pre()
def pre():
print('我在pre()函数里...')
next()
答:有些编程语言不够“聪明”,向这类向前引用的方式会导致报错,但Python足够“醒目”,这段代码是正确的!
会输出:
我在next()函数里...
我在pre()函数里...
1*. 请问以下这个函数有返回值吗?
>>> def hello():
print('Hello FishC!')
如果没有使用return语句指定返回值,Python也不是什么都不返回的,Ta会返回一个None对象,所以我们说Python所有的函数都有返回值。
>>> def hello():
print('Hello FishC!')
>>> temp = hello()
Hello FishC!
>>> temp
>>> print(temp)
None
2. 请问Python的return语句可以返回多个不同类型的值吗?
答:可以,默认用逗号隔开,是以元祖的形式返回,你当然也可以用列表包含起来返回:
>>> def myFun():
return '我爱Python', 520, 3.14, True
>>> myFun()
('我爱Python', 520, 3.14, True)
>>> def myFun2():
return ['小甲鱼', 1314, 5.12, False]
>>> myFun2()
['小甲鱼', 1314, 5.12, False]
>>>
4*. 目测以下程序会打印什么内容?
var = ' Hi '
def fun1():
global var #定义全局变量 var
var = ' Baby '
return fun2(var)
def fun2(var):
var += 'I love you'
fun3(var)
return var
def fun3(var):
var = ' 小甲鱼 '
print(fun1())
答:会打印:
baby I love you
小甲鱼建议不到万不得已不要使用全局变量,简洁的概括为:
a) 代码可读性变差
b) 代码安全性降低
动动手
0. 编写一个函数power()模拟内建函数pow(),即power(x, y)为计算并返回x的y次幂的值。
答:代码如下:
def power(x, y):
result = 1
for i in range(y):
result *= x
return result
print(power(2, 3))
1. 编写一个函数,利用欧几里得算法求最大公约数,例如gcd(x, y)返回值为参数x和参数y的最大公约数。
答:欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。
最大公约数(Greatest Common Divisor)缩写为GCD。代码如下:
def gcd(x,y):
while True:
temp=x%y
if temp==0:
break
x=y
y=temp
return y
print(gcd(1997,615))
2*. 编写一个将十进制转换为二进制的函数,要求采用“除2取余”的方式,结果与调用bin()一样返回字符串形式。
答:十进制转二进制方法如下:
(1)十进制整数转换为二进制整数采用"除2取余,逆序排列"法。具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为小于1时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
(2)十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。
我的实现代码如下:
def trans(dnum):
blist=[]
result=""
if type(dnum)==int:
while True:
temp=dnum%2
blist.insert(0,temp)
dnum=dnum//2
if dnum==0:
break
result=str(blist)
return result
else:
print("数据类型错误!")
print(trans(18))
我的代码最后结果输出格式不是字符串类型的, 我查了一下 str() 的用法,发现 str() 会把整个列表转变为字符串包括方括号,就是把 [1,0,0,1,0] 变为"[1,0,0,1,0]"这样。
所以要把列表变为字符串不能只简单的调用一次 str() ,可以学习小甲鱼提供代码中的方法,将列表中的元素一个一个的转变为字符串。
还有就是这个代码没有实现十进制小数转变为二进制的功能。
小甲鱼提供的代码如下:
def Dec2Bin(dec):
temp = []
result = ''
while dec:
quo = dec % 2
dec = dec // 2
temp.append(quo)
while temp:
result += str(temp.pop())
return result
print(Dec2Bin(62))
0. 编写一个符合以下要求的函数:
a) 计算打印所有参数的和乘以基数(base=3)的结果
b) 如果参数中最后一个参数为(base=5),则设定基数为5,基数不参与求和计算。
答:代码如下:
def mFun(*param, base=3):
result = 0
for each in param:
result += each
result *= base
print('结果是:', result)
mFun(1, 2, 3, 4, 5, base=5)
该题有一个问题就是:题目没有给出函数形参的具体个数,此前定义的函数形参个数都是明确的,所以这块是一个新东西。
1*. 寻找水仙花数
题目要求:如果一个3位数等于其各位数字的立方和,则称这个数为水仙花数。例如153 = 13+53+3^3,因此153是一个水仙花数。编写一个程序,找出所有的水仙花数。
答:代码如下:
def water_flower():
for each in range(100,1000):
a=(each//100)%10 # 注意这里用地板除
b=(each//10)%10
c=each%10
if a**3+b**3+c**3==each:
print(each)
water_flower()
运行结果如下:
小甲鱼提供的代码如下:
def Narcissus():
for each in range(100, 1000):
temp = each
sum = 0
while temp:
sum = sum + (temp%10) ** 3
temp = temp // 10 # 注意这里用地板除
if sum == each:
print(each, end='\t')
print("所有的水仙花数分别是:", end='')
Narcissus()
小甲鱼提供的代码更好,更具一般性。而我写的代码只适合三位数的情况,学习学习!
2. 编写一个函数 findstr()
该函数统计一个长度为 2 的子字符串在另一个字符串中出现的次数。例如:假定输入的字符串为“You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted.”,子字符串为“im”,函数执行后打印“子字母串在目标字符串中共出现 3 次”。
答:代码如下:
def findstr():
str2=input("请输入目标字符串: ")
str3=input("请输入子字符串(两个字符): ")
sum=0
for each in range(len(str2)):
if str2[each]==str3[0]:
if each ==len(str2)-1:
break
elif str2[each+1]==str3[1]:
sum+=1
else:
continue
else:
continue
print(f"子字符串在目标字符串中共出现 {sum} 次")
findstr()
0. 编写一个函数,判断传入的字符串参数是否为“回文联”(回文联即用回文形式写成的对联,既可顺读,也可倒读。例如:上海自来水来自海上)
程序执行结果如图:
答:代码如下:
方法一:
def judge():
str1=input("请输入一句话: ")
length=len(str1)
for each in range(int(length//2)):
if str1[each]==str1[length-1-each]:
continue
else:
print("不是回文联!")
return
print("是回文联!")
judge()
方法二:
def palindrome(string):
list1 = list(string)
list2 = reversed(list1)
if list1 == list(list2):
return '是回文联!'
else:
return '不是回文联!'
print(palindrome('上海自来水来自海上'))
1. 编写一个函数,分别统计出传入字符串参数(可能不只一个参数)的英文字母、空格、数字和其它字符的个数。
程序执行结果如图:
答:代码如下:
def count(*param):
length = len(param)
for i in range(length):
letters = 0
space = 0
digit = 0
others = 0
for each in param[i]:
if each.isalpha():
letters += 1
elif each.isdigit():
digit += 1
elif each == ' ':
space += 1
else:
others += 1
print('第 %d 个字符串共有:英文字母 %d 个,数字 %d 个,空格 %d 个,其他字符 %d 个。' % (i+1, letters, digit, space, others))
count('I love fishc.com.', 'I love you, you love me.')