educoder:Python函数(二)※

第1关:函数的参数 - 搭建函数房子的砖

任务描述

当我们需要在程序中多次执行同一类型的任务时,不需要反复编写代码段来完成任务,而是可以利用函数工具来大大方便我们的编程工作。函数是可重复使用的,用来实现相关联功能的代码段。

本实训的目标是让读者了解并掌握函数结构的相关知识,本关的小目标则是让读者先了解并掌握函数参数的有关知识。

相关知识

我们在使用函数前,得先定义一个满足自己使用要求的函数。定义函数的基本结构是:

  1. def functionname( parameters ):
  2. "函数_文档字符串"
  3. function_suite
  4. return [expression]
  • 定义函数以def关键词开头,后面跟着函数名、圆括号()、括号中的参数、冒号;
  • 接着,在缩进块中编写函数体,函数的第一行语句一般是写文档字符串,用于存放函数说明,也可以选择不写;
  • Return[expression]表示结束函数,并返回值。而不带表达式的return相当于返回空值。

本关的重点就是研究函数的参数parameters。定义函数的时候,参数的名字和位置定下来了,函数的接口定义也就完成了。我们在调用函数时,只用知道该传递什么样的参数,函数内部的运行情况已经被封装,使用者不必了解。

Python的函数参数主要包含以下几种:

  • 必选参数;
  • 默认参数;
  • 可变参数;
  • 关键字参数。

必选参数

必选参数也叫位置参数,是函数中最常用的参数,必选参数就是在调用函数的时候必须指定参数值,例如:

  1. #定义加法函数plus,参数a,b就是必选参数
  2. def plus(a,b):
  3. c=a+b
  4. return(c)
  5. #调用函数plus时,必须给参数a,b传递值
  6. d=plus(1,2)
  7. #输出结果d
  8. print(d)

输出结果:

3

如果调用plus函数时,传入的参数不符合要求,例如:

>>d = plus() TypeError: plus() missing 2 required positional arguments: 'a' and 'b'

>>d = plus(1) TypeError: plus() missing 1 required positional argument: 'b'

默认参数

默认参数是指给函数参数提供默认值,如果在调用函数的时候没有给该参数传递值,则该参数使用默认值。例如:

  1. #定义加法函数plus,参数a是必选参数,参数b是默认值2的参数
  2. def plus(a,b=2):
  3. c=a+b
  4. return(c)
  5. #调用函数plus时,必须给参数a传递值,若不给b传递值,则b默认为2
  6. d=plus(1)
  7. #输出结果d
  8. print(d)

从上面的例子可以看出,在函数调用过程中可以不用给默认参数传递参数值。但在使用默认参数时,有两点需要注意:

  • 默认参数要放在所有必选参数的后面;
  • 默认参数必须指向不变对象。

可变参数

在有些情况下,我们在定义函数的时候,还不能确定函数应该包含多少个参数,这时我们可以使用可变参数,可变参数就是传入的参数数量是可变的。例如:

  1. #定义plus函数,完成的功能是返回输入的整数之和。
  2. # 参数numbers是可变参数,表示输入的参数个数可以为任意值
  3. def plus(*numbers):
  4. add = 0
  5. for i in numbers:
  6. add += i
  7. return(add)
  8. #调用3次plus函数,每次的参数个数都不相同
  9. d1 = plus(1,2,3)
  10. d2 = plus(1,2,3,4)
  11. d3 = plus(1,3,5,7,9)
  12. #向函数中可以传递任意参数,包括0个参数
  13. d4 = plus()
  14. #输出结果
  15. print(d1)
  16. print(d2)
  17. print(d3)
  18. print(d4)

输出结果:

6 10 25 0

在上面的例子中,numbers 就是一个可变参数,可变参数前面加一个标识符*,在函数内部,可变参数numbers接收到的值是一个 tuple

我们在调用参数是可变参数的函数时,可以给该函数传递任意个数的参数,包括0个参数。

关键字参数

可变参数允许我们在调用函数时传入任意个参数,这些可变参数在函数调用时自动组装为一个tuple

而关键字参数允许我们传入任意个含参数名的参数,这些关键字参数在函数调用时自动组装为一个dict。也就是说,关键字参数将长度任意的键-值对, 作为参数传递给函数。

  1. #定义一个包含关键字参数的函数,返回值为参数值
  2. def plus(**kw):
  3. return kw
  4. #调用plus函数,参数值为空
  5. d1 = plus()
  6. #调用plus函数,参数值为x=1
  7. d2 = plus(x=1)
  8. #调用plus函数,参数值为x=1,y=2
  9. d3 = plus(x=1, y=2)
  10. #输出d1,d2,d3
  11. print(d1)
  12. print(d2)
  13. print(d3)

输出结果:

{} {'x': 1} {'x': 1, 'y': 2}

在上面的例子中,kw就是一个关键字参数,关键字参数前面加两个*表示,关键字参数可以扩展函数功能,使传递参数过程更为简便,例如:

  1. #定义一个plus函数,有3个参数,返回值是3个参数之和
  2. def plus(x,y,z):
  3. return x+y+z
  4. #有一个dict列表,当中3个键的值分别为1,2,3
  5. dict = {'x':1, 'y':2, 'z':3}
  6. #将dict列表中的3个值传入plus函数中,得到返回值d
  7. d = plus(dict['x'],dict['y'],dict['z'])
  8. #输出d
  9. print(d)

输出结果:

6

但在上述例子中,将字典中的值向plus函数中传递参数的方法过于累赘,可以采取关键字参数的方法。例如:

  1. #定义一个plus函数,有3个参数,返回值是3个参数之和
  2. def plus(x,y,z):
  3. return x+y+z
  4. #有一个dict列表,当中3个键的值分别为1,2,3
  5. dict = {'x':1, 'y':2, 'z':3}
  6. #用关键字参数的方法将dict列表中的3个值传入plus函数中,得到返回值d
  7. d = plus(**dict)
  8. #输出d
  9. print(d)

输出结果:

6

使用关键字参数**dict的方法,可以大大提高参数传递的效率。

参数组合

我们在函数定义过程中,可以同时用到必选参数,默认参数,可变参数,关键字参数中的一种或几种。但是,需要特别注意的是,这四种参数在使用的过程中是有顺序的,顺序依次应该是必选参数、默认参数、可变参数和关键字参数。

例如:

  1. #定义一个包含必选参数、默认参数、可变参数和关键字参数的函数plus
  2. def plus(x, y, z=0, *args, **kw):
  3. print('x=',x)
  4. print('y=',y)
  5. print('z=',z)
  6. print('args=',args)
  7. print('kw=',kw)
  8. #调用函数plus,输入两个参数1,2
  9. plus(1,2)

输出结果:

  1. x= 1
  2. y= 2
  3. z= 0
  4. args= ()
  5. kw= {}

上面这个例子向plus函数中传入了两个必选参数12,必选参数是必须得提供值,但是默认参数、可变参数和关键字参数可以不用提供值。

我们还可以给默认参数、可变参数和关键字参数传递值,例如:

  1. 定义一个包含必选参数、默认参数、可变参数和关键字参数的函数plus
  2. def plus(x, y, z=0, *args, **kw):
  3. print('x=',x)
  4. print('y=',y)
  5. print('z=',z)
  6. print('args=',args)
  7. print('kw=',kw)
  8. #调用函数plus,输入参数x=1,y=2,z=3,args=(4,5,6),kw={}
  9. plus(1,2,3,4,5,6)
  10. print('\n')
  11. #调用函数plus,输入参数x=1,y=2,z=3,args=(4,5,6),kw={'k':7, 'm':8}
  12. plus(1,2,3,4,5,6,k=7,m=8)

输出结果:

  1. x= 1
  2. y= 2
  3. z= 3
  4. args= (4, 5, 6)
  5. kw= {}
  6. x= 1
  7. y= 2
  8. z= 3
  9. args= (4, 5, 6)
  10. kw= {'k': 7, 'm': 8}

小结

  • 不同类型的参数是有顺序的,依次是必选参数、默认参数、可变参数和关键字参数;
  • 默认参数一定要用不可变对象,用可变对象容易产生逻辑错误;
  • *args表示的是可变参数,*args接收的是一个元组;
  • **kw表示的是关键字参数,**kw接收的是一个字典。

编程要求

本关的编程任务是补全src/Step1/plus.py文件的代码,实现相应的功能。具体要求如下:

  • 定义函数plus,功能是对参数(一个列表)中的数值元素进行累加,列表中的元素个数不确定;
  • 函数返回累加结果。

本关涉及的代码文件src/Step1/plus.py的代码框架如下:

  1. #coding=uft-8
  2. #创建一个空列表numbers
  3. numbers = []
  4. #str用来存储输入的数字字符串,lst1是将输入的字符串用空格分割,存储为列表
  5. str = input()
  6. lst1 = str.split(' ')
  7. #将输入的数字字符串转换为整型并赋值给numbers列表
  8. for i in range(len(lst1)):
  9. numbers.append(int(lst1.pop()))
  10. # 请在此添加函数plus的代码,函数参数为一个列表
  11. #********** Begin *********#
  12. #********** End **********#
  13. d = plus(numbers)
  14. print(d)

测试说明

本关的测试文件是src/Step1/plus.py,测试过程如下:

  1. 平台自动编译生成plus.exe;
  2. 平台运行plus.exe,并以标准输入方式提供测试输入;
  3. 平台获取plus.exe输出,并将其输出与预期输出对比。如果一致则测试通过,否则测试失败。

以下是平台对src/Step1/plus.py的样例测试集:

测试输入: 1 2 3 4 5 预期输出: 15

测试输入: 1 3 5 7 9 11 预期输出: 36

测试输入: 2 4 6 8 10 12 14 16 预期输出: 72


开始你的任务吧,祝你成功!

明明每天都无所事事,却也感觉不到半点轻松。不如去运动吧

如果你觉得这一关的内容对你有帮助,请你在下面点赞。

代码:

#coding=utf-8

#创建一个空列表numbers
numbers = []

#str用来存储输入的数字字符串,lst1是将输入的字符串用空格分割,存储为列表
str = input()
lst1 = str.split(' ')

#将输入的数字字符串转换为整型并赋值给numbers列表
for i in range(len(lst1)):
   numbers.append(int(lst1.pop()))

# 请在此添加函数plus的代码,函数参数为一个列表,对列表中的数值元素进行累加求和
#********** Begin *********#
def plus(numbers):
   add=0
   for i in numbers:
      add+=i
   return add
#********** End **********#

#调用plus函数,并将返回结果存储到变量d中
d = plus(numbers)
print(d)








第2关:函数的返回值 - 可有可无的return

任务描述

函数在进行运算处理后,返回的值被称为返回值。函数返回的值是通过return语句执行。返回值能够让我们直接得到函数处理的结果,而不必关心函数内部复杂繁重的运算过程,大大提高了编程效率。

本关的主要目标是让读者了解并掌握函数返回值的相关知识。

相关知识

return语句将值返回到调用函数的出口,函数中一定要有return返回值才是完整的函数。如果我们没有在函数中定义函数返回值,那么程序会自动让函数返回一个结果,该结果是None对象,而None对象表示没有任何值。

将值作为返回值

函数的返回值只有一个,但有时我们会发现有的函数好像有多个返回值。其实这里的“多个”并不是多个返回值,比如函数返回一列表,里面包含很多个元素值。这就类似于:只能从超市带走一个箱子,但是允许我们把一些东西都装到箱子里面看做一个东西带走。例如:

  1. def f():
  2. return 1,'abc','1234'
  3. print(f())

输出结果:

(1, 'abc', '1234')

调用f()函数,程序输出为一个元组,所以函数返回值表面上是3个值,其实是返回一个元组,元组里面有三个不同元素(元组语法上不需要一定要带上圆括号)。

将函数作为返回值

我们除了可以将各种类型的值作为返回值外,也可以将函数作为返回值。

例如,我们要定义一个函数来求列表中数值元素的和,一般情况下我们是这样定义的:

  1. def plus(*args):
  2. s = 0
  3. for n in args:
  4. s = s + n
  5. return s

但是,如果我们不需要立刻求和,而是在后面的程序中,根据需求再计算怎么办?这时我们定义的函数可以不返回求和的结果,而是返回计算求和的函数!

所以我们还可以用如下方法定义函数:

  1. def lazy_plus(*args):
  2. def plus():
  3. s = 0
  4. for n in args:
  5. s = s + n
  6. return s
  7. return plus

当我们调用lazy_plus()时,返回的并不是求和结果,而是计算求和的函数:

  1. #定义求和函数,返回的并不是求和结果,而是计算求和的函数
  2. def lazy_plus(*args):
  3. def plus():
  4. s = 0
  5. for n in args:
  6. s = s + n
  7. return s
  8. return plus
  9. #调用lazy_plus()时,返回的并不是求和结果,而是求和函数
  10. f = lazy_plus(1,2,3,4,5)
  11. print(f)

输出结果:

<function lazy_plus.<locals>.plus at 0x000001DAC97F9950>

调用函数f时,才真正计算求和的结果:

  1. #定义求和函数,返回的并不是求和结果,而是计算求和的函数
  2. def lazy_plus(*args):
  3. def plus():
  4. s = 0
  5. for n in args:
  6. s = s + n
  7. return s
  8. return plus
  9. #调用函数f时,得到真正求和的结果
  10. f = lazy_plus(1,2,3,4,5)
  11. print(f())

输出结果:

15

在上述例子中,我们在函数lazy_plus中又定义了函数plus,而且内部函数plus是可以引用外部函数lazy_plus的参数和局部变量的,当函数lazy_plus返回函数plus时,相关参数和变量也将会保存在返回的函数中,这种方式也称为“闭包(Closure)”

小结:我们除了可以将函数计算的值作为返回值外,也可以将函数作为返回值。

如果您想了解更多有关列表操作知识,请参考:【美】Eric Matthes著《Python编程——从入门到实践》第八章

编程要求

本关的编程任务是补全src/step2/return.py文件的代码,实现相应的功能。具体要求如下:

  • 定义一个函数gcd,功能是求两个正整数的最大公约数;

本关涉及的代码文件src/step2/return.py的代码框架如下:

  1. #coding=utf-8
  2. #输入两个正整数a,b
  3. a = int(input())
  4. b = int(input())
  5. # 请在此添加函数gcd代码,求两个正整数的最大公约数
  6. #********** Begin *********#
  7. #********** End **********#
  8. #调用函数,并输出最大公约数
  9. print(gcd(a,b))

测试说明

本关的测试文件是src/step2/return.py,测试过程如下:

  1. 平台自动编译生成return.exe
  2. 平台运行return.exe,并以标准输入方式提供测试输入;
  3. 平台获取return.exe输出,并将其输出与预期输出对比。如果一致则测试通过,否则测试失败。

以下是平台对src/step2/return.py的样例测试集:

测试输入: 1 8 预期输出: 1

测试输入: 9 3 预期输出: 3

测试输入: 9 21 预期输出: 3

测试输入: 126 36 预期输出: 18


开始你的任务吧,祝你成功!

总有人比自己更优秀、更帅、更春风得意。接受这个现实,但你还是要做自己心中的王。

如果你觉得这一关的内容对你有帮助,请你在下面点赞。

代码:

#coding=utf-8

#输入两个正整数a,b
a = int(input())
b = int(input())

# 请在此添加函数gcd代码,求两个正整数的最大公约数
#********** Begin *********#
def gcd(a,b):
    if a<b:
        t=a
        a=b
        b=t
    while b:
        maxs=a%b
        a=b
        b=maxs
    return a

#********** End **********#

#调用函数,并输出最大公约数
print(gcd(a,b))


第3关:函数的使用范围:Python作用域

任务描述

函数是有使用范围的,在一个模块中,我们可以定义很多函数和变量,但我们希望有的函数和变量别人可以使用,有的函数和变量仅仅可以在模块内部使用。这就是Python作用域的相关问题。

本关的目标就是让读者了解并掌握函数的使用范围,即Python作用域的相关知识。

相关知识

Python中,正常的函数和变量名是公开的(public),都是可以被直接引用的,比如:abs()abcdir()等。

类似__xxx__这种格式的变量是特殊变量,允许被直接引用,但是会被用作特殊用途,比如__author____name__就是属于特殊变量。hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己编程定义的变量一般不会用这种变量名。

类似_xxx__xxx这种格式的函数和变量就是非公开的(private),不应该被直接引用。

补充:_xxx的函数和变量是protected,我们直接从外部访问不会产生异常。__xxx的函数和变量是private,我们直接从外部访问会报异常,我们要注意前缀符号的区别。

我们要注意用词的区别,我们说的是private函数和变量是“不应该”被直接引用,而不是“不能”被直接引用,这是因为在Python种并没有一种方法可以真正完全限制访问private函数或变量。但是我们为了养成良好的编程习惯,是不应该引用private函数或变量的。

private函数的作用是隐藏函数的内部逻辑,让函数有更好的封装性。

例如:

  1. def _private_1(name):
  2. return 'Hello, %s' % name
  3. def _private_2(name):
  4. return 'Hi, %s' % name
  5. def greeting(name):
  6. if len(name) > 3:
  7. return _private_1(name)
  8. else:
  9. return _private_2(name)

我们在上述程序块里公开了greeting()函数,greeting()函数需要使用_private_1()_private_2()函数,读者并不需要知道greeting()函数中的内部实现细节。所以我们可以将内部逻辑用private函数隐藏起来。这是一种十分常用的代码封装的方法。

小结:为了让程序的封装性更好,我们一般都限定函数的使用范围,一般我们把外部需要使用的函数定义为public函数,而把只在内部使用,而外部不需要引用的函数定义成private函数。

编程要求

本关的编程任务是补全src/step3/scope.py文件的代码,实现相应的功能。具体要求如下:

  • 编写程序,功能是求两个正整数的最小公倍数;
  • 要求实现方法:先定义一个private函数 _gcd()求两个正整数的最大公约数,再定义public函数lcm()调用 _gcd()函数求两个正整数的最小公倍数。

本关涉及的代码文件src/step3/scope.py的代码框架如下:

  1. #coding=utf-8
  2. #输入两个正整数a,b
  3. a = int(input())
  4. b = int(input())
  5. # 请在此添加一个private函数_gcd()求两个正整数的最大公约数
  6. #********** Begin *********#
  7. #********** End **********#
  8. # 请在此添加一个public函数lcm(),通过调用_gcd()求两个正整数的最小公倍数
  9. #********** Begin *********#
  10. #********** End **********#
  11. #调用函数,并输出a,b的最小公倍数
  12. print(lcm(a,b))

测试说明

本关的测试文件是src/step3/scope.py,测试过程如下:

  1. 平台自动编译生成scope.exe;
  2. 平台运行scope.exe,并以标准输入方式提供测试输入;
  3. 平台获取scope.exe输出,并将其输出与预期输出对比。如果一致则测试通过,否则测试失败。

以下是平台对src/step3/scope.py的样例测试集:

测试输入: 5 6 预期输出: 30

测试输入: 8 10 预期输出: 40

测试输入: 16 24 预期输出: 48

测试输入: 132 214 预期输出: 14124


开始你的任务吧,祝你成功!

路程中会遇到很多很多麻烦困难,我们需要承受,更要去解决,俞敏洪说过一句话:坚持下去,不是我们有足够的坚强,而是我们已经无法选择。

如果你觉得这一关的内容对你有帮助,请你在下面点赞。

代码:

#coding=utf-8

#输入两个正整数a,b
a = int(input())
b = int(input())

# 请在此添加一个private函数_gcd()求两个正整数的最大公约数
#********** Begin *********#
def gcd(a,b):
    if a<b:
        t=a
        a=b
        b=t
    while b:
        maxs=a%b
        a=b
        b=maxs
    return a

#********** End **********#

#请在此添加一个public函数lcm(),在lcm()函数中调用_gcd()函数,求两个正整数的最小公倍数
#********** Begin *********#

def lcm(a,b):
    return int(a*b/gcd(a,b))


#********** End **********#


#调用函数,并输出a,b的最小公倍数
print(lcm(a,b))

第4关:函数综合训练※

任务描述

本关任务:利用函数的知识完成如下习题。

相关知识(略)

编程要求

根据提示,在右侧编辑器Begin-End处补充代码,完成如下要求:

第一题

若三角形的三边分别为a,b,c ,令p=(a+b+c)/2,则该三角形的面积为:

S=p(p−a)(p−b)(p−c)​

本题将利用triArea函数计算如下图阴影部分的面积,并打印出结果。你的任务是编程实现函数triArea(a,b,c),利用上述公式计算三角形的面积。

第二题

本题通过编程验证哥德巴赫猜想,即:任何一个大于或等于6的偶数,可以表示成两个素数之和。例如:11111112 = 11 + 11111101 。你的任务:1)编程实现一个函数isPrime(x),判断整数x是否为素数;2)程序将使用函数Goldbach(N)将整数N分解成两素数之和以验证哥德巴赫猜想,你需要补充完整该函数代码。

第三题

已知某型迫击炮发射初速度为300m/s, 炮弹飞行过程中无动力,不考虑空气阻力,重力加速度取9.8m2/s。在不同的角度下,炮弹落地的时间与飞行的位置都不一样。本题通过编程绘制角度分别为[30, 45, 60, 75]度时的炸弹轨迹。其中函数calBombT\frace(theta)计算炮弹飞行过程中n个位置坐标,时间样本为均匀分配。你的任务是补充完整该程序代码。

计算逻辑示例如下(编程时不需要取整):

当角度为为30度时,炸弹空中飞行时间约为30.6s

若取5个均匀的时间样本,分别约为[ 0, 7.6, 15.3, 22.9, 30.6 ]

则对应的x坐标则为[0,1988, 3976, 5964, 7953]

对应的y坐标则为[ 0, 860,1147, 860, 0 ]

第四题

如图所示,一致函数的方程为

f(x)=exsin(x)

求函数曲线在[0,pi]区间的长度。 你的任务:1)编写函数f(x)计算上述函数的值;2)编写函数pt(a, b)利用勾股定理计算直角三角形的斜边长。

提示:把区间分成n个小区间,曲线可以近似看成线段。当小区间的区间数量足够多时,近似长度接近真实值。

测试说明

平台会对你编写的代码进行测试: 测试输入:

60

30

预期输出:

  1. 24.201994
  2. 60 = 7 + 53
  3. [0.0, 158.339198, 316.678395, 475.017593, 633.356791, 791.695989, 950.035186, 1108.374384, 1266.713582, 1425.05278, 1583.391977, 1741.731175, 1900.070373, 2058.409571, 2216.748768, 2375.087966, 2533.427164, 2691.766362, 2850.105559, 3008.444757, 3166.783955, 3325.123153, 3483.46235, 3641.801548, 3800.140746, 3958.479944, 4116.819141, 4275.158339, 4433.497537, 4591.836735]
  4. [0.0, 570.553037, 1100.352285, 1589.397745, 2037.689417, 2445.2273, 2812.011395, 3138.041702, 3423.31822, 3667.84095, 3871.609892, 4034.625045, 4156.88641, 4238.393987, 4279.147775, 4279.147775, 4238.393987, 4156.88641, 4034.625045, 3871.609892, 3667.84095, 3423.31822, 3138.041702, 2812.011395, 2445.2273, 2037.689417, 1589.397745, 1100.352285, 570.553037, 0.0]
  5. l = 15.476558

开始你的任务吧,祝你成功!

代码:

import numpy as np

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt     #导入matplotlib.pyplot
# 第一题
######## begin ###########
# 请编写函数triArea(a ,b , c),返回三角形的面积
def triArea(a,b,c):
    p=((a+b+c)/2)
    S=pow(p*(p-a)*(p-b)*(p-c),1/2)
    return(S)
######## end #########
S1 = triArea(9.8, 9.3, 6.4)
S2 = triArea(2.9, 4.1, 4.7)
S3 = triArea(2.0, 1.4, 2.3)
print('%.6f' %(S1-S2+S3))
# 第二题
######## begin ###########
# 请编写函数isPrime(x)。判断x是否是素数,返回True或者False
def isPrime(x):
    n=0
    for i in range(2,x//2):
         if x%i==0:
            n+=1
    if n==0:
        return("True")
    else:
        return("False")
#######  end    ############
def Goldbach(N):  # 将N分解成两素数之和
    if N < 6 or N % 2 == 1:  # 若N小于6或N为奇数
        print('N应该是大于等于6的偶数')
    else:
        # 循环判断,得到符合要求的小于N的两个素数,并打印
        for x in range(2, N // 2):  # 想想为什么是从2到N/2
            # 调用isPrime函数,得到符合要求的小于N的两个素数
            ######## begin ###########
            if isPrime(x)=="True" and isPrime(N-x)=="True":
            ######## end ###########
                print(N, '=', x, '+', N - x)
                break
N = int(input())
Goldbach(N)
# 第三题
# calBombTrace 函数
def calBombTrace(theta):
    v0, g, n = 300, 9.8, 30
    theta_d = np.radians(theta)     #因numpy中cos、sin的输入为弧度值,故先将theta从度转换为弧度
    v0_x = v0*np.cos(theta_d)       #炮弹水平初速度
    v0_y = v0*np.sin(theta_d)       #炮弹垂直初速度
    tmax = 2*v0_y/g                 #落地时间,即v0_y*t-0.5gtt=0的解
    t = np.linspace(0, tmax, n)     #n个时刻
    xt = v0_x*t                     #n个时刻的横坐标
    yt = v0_y*t-1/2*g*t**2          #n个时刻的纵坐标
    return xt, yt
for theta in [30, 45, 60, 75]:
    ############ begin #########
    # 调用函数,得到theta返回的值,并存储到xt与yt变量
    xt,yt=calBombTrace(theta)
    ########### end #############
    plt.plot(xt, yt)
plt.grid('on')
plt.axis([0, 10000, 0, 5000])
plt.savefig('./src/step4/res/轨迹.png')
plt.close()
print([round(x,6) for x in xt])
print([round(x,6) for x in yt])
# 第四题
# 在此添加代码,编写函数f(x),计算f(x)的值
from math import * 
########### begin #############
def f(x):
    a=((np.e)**x)*(np.sin(x))
    return(a)
########### end #############
# 在此添加代码,编写函数pt(a, b),利用勾股定理计算直角三角形的斜边长
########### begin #############
def pt(a, b):
    c=pow(a**2+b**2,1/2)
    return(c)
########### end ############
n = 1000  # 细分成n个子区间
x = np.linspace(0, np.pi, n + 1)  # n个子区间的n+1个端点
l, h = 0, np.pi / n  # l为曲线长度、h为子区间宽度
for i in range(n):  # 对每个子区间
    li = pt(f(x[i + 1]) - f(x[i]), h)  # 曲线在第i个子区间的近似长度
    l += li  # 将航渡累加到l中
print('l = %.6f' %l)
要实现网络攻防的模拟实训,首先需要了解虚拟化技术的基础,它允许你在同一台物理机器上运行多个虚拟机(VM),每个VM都像是独立的物理机器一样运行不同的操作系统和应用程序。在这个过程中,PY-Prac9平台为用户供了便捷的虚拟化环境设置和管理工具。具体步骤如下: 参考资源链接:[磐云网络空间安全实训平台PY-Prac9:实战教学与安全环境](https://wenku.youkuaiyun.com/doc/6ymoyobmf9?spm=1055.2569.3001.10343) 1. **环境准备**:确保PY-Prac9实训平台已经安装并且运行稳定。如果还没有安装,请根据《磐云网络空间安全实训平台PY-Prac9:实战教学与安全环境》的指南进行安装。 2. **创建虚拟机**:登录到PY-Prac9平台,选择创建新的虚拟机选项。你可以根据教学需要选择不同的操作系统镜像,如Kali Linux用于安全测试,或者Windows Server用于模拟企业环境。 3. **配置网络**:为了模拟真实网络环境,需要设置虚拟网络。通过平台供的网络管理工具,你可以创建虚拟网络,并将虚拟机连接到这些网络中。可以设置不同网络之间的隔离或互通,以此模拟复杂的网络场景。 4. **部署服务与应用**:在虚拟机上安装和配置网络服务,如Web服务器、数据库服务器等。这些服务将作为攻击和防御的模拟对象。 5. **设置攻击和防御规则**:根据实训内容,设定相关的安全规则和策。例如,配置防火墙规则,允许或拒绝特定类型的流量。 6. **执行模拟攻击**:在安全的虚拟化环境中,使用如Metasploit这样的工具进行攻击模拟。通过这些工具,你可以对虚拟机上的服务发起攻击,以学习攻击行为和防御机制。 7. **监控和日志分析**:在实训过程中,利用平台的日志管理和监控功能,记录实训活动,分析网络流量和攻击行为,从而加深对网络攻防过程的理解。 8. **复原环境**:实训完成后,利用平台供的环境复原功能,将虚拟机恢复到初始状态,为下一轮实训做好准备。 通过以上步骤,结合《磐云网络空间安全实训平台PY-Prac9:实战教学与安全环境》供的指导,即使是网络空间安全的初学者也能在模拟环境中学习和体验网络攻击和防御的实战过程。这不仅增强了学生的实践技能,也为他们未来的网络安全职业道路奠定了坚实基础。 参考资源链接:[磐云网络空间安全实训平台PY-Prac9:实战教学与安全环境](https://wenku.youkuaiyun.com/doc/6ymoyobmf9?spm=1055.2569.3001.10343)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值