python基础知识--6函数
1.函数的特点
print pow input sorted 等等
# 1.功能强大;
# 2.调用方便;
# 3.灵活高效。
# 1.功能强大
# 内置函数,或自定义函数内部,可以根据不同需求,实现相应的功能。
print('lemon','pear',sep=',',end='*')
运行结果:
lemon,pear*
# 2.调用方便
# 函数内部具体细节的定义可能很复杂,但有时我们不需了解具体细节,只需传入相关参数,就能方便调用函数,实现相应功能。
2 ** 3
运行结果:8
pow(2,3)
运行结果:8
# 3.灵活高效
# Python声明一个函数,不需声明函数返回值类型,也不需说明参数类型。这也符合,Python一切皆对象的特点。
# 写一段程序的时候,可以将相同功能的代码块封装在一个函数里,减少很多重复代码,以提高效率
2.函数的基本形式
def <函数名> (参数):
<函数语句>
return <返回值>
其中注意的地方有:
1.def 声明一个函数;
2.函数名,可自定义,为了避免不必要的麻烦,不建议与 Python关键字,Python内置函数同名;
3.函数参数,不是必须的,可以不填;
4.即使函数不传入任何参数,()是不能省的;
5.默认两个空格缩进的函数语句,表示属于该函数;
6.return 后可以没有返回值,甚至return语句也可省略;
7.return 后没有返回值,或者不写return语句的函数,默认返回的是 None;
help('keywords')
运行结果:
Here is a list of the Python keywords. Enter any keyword to get more help. False def if raise None del import return True elif in try and else is while as except lambda with assert finally nonlocal yield break for not class from or continue global pass
dir(__builtins__)
# 创建简单函数
# 需求1:创建一个函数, 调用该函数的时候打印 hello lemon
def hello():
print('hello lemon')
hello()
运行结果:
hello lemon
# 需求2:创建一个函数, 传入两个值,返回两个值的和
def add(x,y):
result = x + y
return result
add(2,3)
运行结果:5
add(4,6)
运行结果:10
3.函数参数类型
# 无参函数
def hello():
print('hello lemon')
# 有参函数
def add(x,y):
result = x + y
return result
#%%
add(3,2)
#%%
# x,y 形式参数,形参
# 3,2 实际参数,实参
def func_name(param1,*args,param2=0,**kwargs):
pass
声明函数时,可以不定义任何形式参数。
声明函数时,如果需要定义形式参数。形式参数类型有 必须参数、可变参数、默认值参数、可变关键字参数 这四种。
# 定义函数的时候,一般有以下常见形参:
param1 必须参数 (定义了多少个参数,就必须得传递多少个参数)
*args 可变参数 (可以传递任意个参数)
param2 默认值参数 (给参数赋默认值)
**kwargs 可变关键字参数 (可以传递任意个关键字参数)
这4种参数都可以一起使用,或者只用其中某些。
如果要一起使用的话,请注意,参数定义的顺序最好是:
必须参数、可变参数、默认参数和关键字可变参数。
如只需其中某些参数,这些参数的顺序,也应相对固定
4.必须函数
# 必须参数
# 声明一个函数的时候,定义了多少个必须参数,调用函数的时候就必须的传递多少个实参。
# 实参赋值的顺序,对应必须参数定义时的顺序。
def add(x,y):
result = x + y
return result
add(3,2)
运行结果:5
# 个人建议:
# 不建议大家定义过多必须参数。
# 如果大家真的需要定义多个必须参数,建议大家,可将多个必须参数封装成一个对象,把对象传入到函数中。
# 需求:创建一个函数,录入 苹果,柠檬 两种水果数量,并打印详情
def detail(apple,lemon):
print('apple的数量为:' + str(apple))
print('lemon的数量为:' + str(lemon))
detail(4)
运行结果:
TypeError Traceback (most recent call last)
<ipython-input-4-50154db873ac> in <module>() ----> 1 detail(4)
TypeError: detail() missing 1 required positional argument: 'lemon'
detail(4,5)
运行结果:
apple的数量为:4 lemon的数量为:5
# 疑问:假如我调用函数的时候,记不住参数的顺序,那该怎么办?
# 关键字参数,可以在调用函数的时候,告诉Python,我们赋值的实参,到底是传递给哪个参数。
detail(apple=10,lemon=8)
运行结果:
apple的数量为:10 lemon的数量为:8
# 使用关键字参数,特点:
# 1.没有改变函数行为,增强代码的可读性。
# 2.不需强制记忆参数的顺序,可任意调换参数传递的顺序。
5.默认参数值
def func_name(param1 = 'default1',param2 = 'default2'):
pass
# 默认值参数,指的是,参数在定义时,设置的默认值。
# 调用函数的时候,如果需要修改默认值参数,建议使用关键字参数,对默认值参数进行重新赋值。关键字参数,可以不遵循默认值参数顺序。
def message(name,age,sex='male',nationality='China'):
print('我叫:' + str(name) )
print('今年:' + str(age) + ' 岁' )
print('性别::' + str(sex) )
print('国籍为::' + str(nationality) )
message('lemon',8)
运行结果:
我叫:lemon 今年:8 岁 性别::male 国籍为::China
message('Alice',24,sex='female',nationality='USA')
我叫:Alice 今年:24 岁 性别::female 国籍为::USA
message('Alice',24,nationality='USA',sex='female')
我叫:Alice 今年:24 岁 性别::female 国籍为::USA
6.可变参数
# 序列解包
# 序列解包就是,将序列中的元素平铺出来,按照顺序分别赋值给多个变量。
# 序列:字符串、列表、元组
# 序列解包-字符串
s = '123'
a,b,c = s
print('a的值为:' + str(a) + ' 类型为:' + str(type(a)))
print('b的值为:' + str(b) + ' 类型为:' + str(type(b)))
print('c的值为:' + str(c) + ' 类型为:' + str(type(c)))
运行结果:
a的值为:1 类型为:<class 'str'> b的值为:2 类型为:<class 'str'> c的值为:3 类型为:<class 'str'>
# 赋值的变量数量,需要与序列中的元素数量一致
a,b,c = s
# 序列解包-列表
l = [1,2,3]
a,b,c = l
print('a的值为:' + str(a) + ' 类型为:' + str(type(a)))
print('b的值为:' + str(b) + ' 类型为:' + str(type(b)))
print('c的值为:' + str(c) + ' 类型为:' + str(type(c)))
运行结果:
a的值为:1 类型为:<class 'int'> b的值为:2 类型为:<class 'int'> c的值为:3 类型为:<class 'int'>
# 序列解包-元组
tu = (1,2,3)
a,b,c = tu
print('a的值为:' + str(a) + ' 类型为:' + str(type(a)))
print('b的值为:' + str(b) + ' 类型为:' + str(type(b)))
print('c的值为:' + str(c) + ' 类型为:' + str(type(c)))
运行结果:
a的值为:1 类型为:<class 'int'> b的值为:2 类型为:<class 'int'> c的值为:3 类型为:<class 'int'>
def func_args(*args):
print(args)
print(type(args))
# 对于可变参数,我们可传递任意个参数,这些参数在函数调用时自动组装为一个tuple。
# 传入0个参数
func_args()
() <class 'tuple'>
# 传入2个参数
func_args(1,2)
(1, 2) <class 'tuple'>
# 疑问:可否传入一个元祖
a = (1,2)
func_args(a)
运行结果:
((1, 2),) <class 'tuple'>
func_args(*a)
运行结果:
(1, 2) <class 'tuple'>
# * 星号的作用是将元祖里面的元素平铺出来,传递到可变参数的函数里面;
# 如果你想将一个序列内的元素平铺出来,传递到可变参数的函数里面,可使用序列解包操作。
# 此外,大家也可以传递一个字符串、列表到可变参数函数里面,大家下去可以去尝试一下。
# 总结
def func_args(*args):
print(args)
print(type(args))
func_args(1,2,3.....N)
func_args(*seq)
# 1.对于可变参数,我们可以传递任意个参数,
# 2.我们也可以传递一个序列,不过序列前面需要加上一个*
# 需求:创建一个函数,用户可传入任意值,并返回任意值相加后的值
def add_all(*args):
sum = 0
for i in args:
sum += i
return sum
add_all(1,2,3,4)
运行结果:10
a = (1,2,3,4)
add_all(*a)
运行结果:10
7.可变关键字参数
def func_kwargs(**kwargs):
print(kwargs)
print(type(kwargs))
# 可变关键字参数,可传递任意个关键字参数,这些关键字参数在函数调用的时候会自动组装为一个dict。
# 传入0个关键字参数
func_kwargs()
运行结果:
{} <class 'dict'>
# 传入2个关键字参数
func_kwargs(lemon=5,apple=10)
运行结果:
{'lemon': 5, 'apple': 10} <class 'dict'>
# 可否传入一个字典
fruits = {'pear':5,'banana':6}
func_kwargs(**fruits)
运行结果:
{'pear': 5, 'banana': 6} <class 'dict'>
# 这里的 ** 代表将 fruits 字典中的键值对平铺出来,将每个键值对传递到可变关键字参数的函数里面,
# 可变参数 与 可变关键字参数 总结
# 可变参数,
# 1.可传入任意个参数;
# 2.如果传入的是一个序列(字符串、列表、元组),可使用 * ,将每个元素平铺出来,传递到可变参数的函数里面。
# 可变关键字参数
# 1.可传入任意个关键字参数;
# 2.如果传入的是一个字典,可使用 ** ,将每个键值对平铺出来,传递到可变关键字参数函数里面。
8.函数参数类型顺序
# 函数中,如果定义了必须参数,那必须参数最好排在第一位
# 必须参数 与 可变参数
def fruits(*args,lemon):
print(args)
print(lemon)
fruits(4,5,6,7)
def fruits(lemon,*args):
print(lemon)
print(args)
fruits(4,5,6,7)
运行结果:
4 (5, 6, 7)
# 必须参数 与 默认值参数
# 默认值参数,必须要在必须参数后面
def fruits(apple=5,lemon):
print(apple)
print(lemon)
运行结果报错:
File "<ipython-input-90-c31da78cab78>", line 1 def fruits(apple=5,lemon): ^ SyntaxError: non-default argument follows default argument
#%%
def fruits(lemon,apple=5):
print(apple)
print(lemon)
# 可变参数 与 默认值参数
def fruits(apple=5,*args):
print(apple)
print(args)
fruits(1,2,3,4)
运行结果:
1 (2, 3, 4)
#%%
def fruits(*args,apple=5):
print(args)
print(apple)
fruits(1,2,3,4)
运行结果:
(1, 2, 3, 4)
# 总结
#%%
# 必须参数
# 可变参数
# 默认值参数
# 可变关键字参数
# 函数中,如果定义了可变关键字参数,那可变关键字参数顺序必须要排在最后一位
def func_name(param1,*args,param=0,**kwargs):
pass
#%%
def func_name(**kwargs,param1,*args,param=0):
pass
运行结果报错:
File "<ipython-input-98-969db299e548>", line 1 def func_name(**kwargs,param1,*args,param=0): ^ SyntaxError: invalid syntax
#%%
def func_name(param1,**kwargs,*args,param=0):
pass
运行结果:
File "<ipython-input-99-1e3c429bf2c0>", line 1 def func_name(param1,**kwargs,*args,param=0): ^ SyntaxError: invalid syntax
#%%
def func_name(param1,*args,**kwargs,param=0):
pass
运行结果:
File "<ipython-input-99-1e3c429bf2c0>", line 1 def func_name(param1,**kwargs,*args,param=0): ^ SyntaxError: invalid syntax
# 建议:
# 1.前期学习的时候,建议大家不要定义过于复杂的形参类型,定义比较简单的形参类型,如 必须参数、默认值参数;
# 2.后期编码的时候,建议大家多多查看别人写的优质代码,不断学习,不断迭代,不断进步。
9.变量作用域
# Python作用域
Python 有哪些作用域:
1.L (Local) 局部作用域
2.E (Enclosing) 嵌套函数外层非全局作用域
3.G (Global) 全局作用域
4.B (Built-in) 内建作用域
# 变量根据作用域的不同,可分为:
# 1.全局变量
# 2.局部变量
# 1.全局变量作用域的范围是:自己编写的整个程序内
# 2.局部变量作用域的范围是:自己编写的整个函数内
#%%
lemon = 5 # 全局变量
def fruit():
lemon = 20 # 局部变量
print(lemon)
# 虽然变量名相同,但作用域范围不同,互相不受影响
# 变量的引用
# 1.函数内部,可以引用全局变量
#%%
lemon = 5
def fruit1():
#lemon = 10
print(lemon)
fruit1()
运行结果:5
# 2.函数外部,一般情况下,不可引用局部变量
def fruit2():
pear = 5
print(pear)
运行结果:
NameError Traceback (most recent call last)
<ipython-input-3-b6b282780e8e> in <module>() 2 pear = 5 3 ----> 4 print(pear)
NameError: name 'pear' is not defined
# 扩展:Python 没有块级作用域
# 疑问:可否从外部引用代码块里面的变量
if 5>0:
lemon = 5
print(lemon)
运行结果:5
#%%
for i in range(10):
lemon = 9
print(lemon)
运行结果:9
#%%
i = 1
while i<3:
lemon = 3
i+=1
print(lemon)
运行结果:3
# 在Python中是没有块级作用域的,if/for/while 代码块里的变量,外部可以调用
10.作用域链
# 作用域链:作用域具有链式查找特性
# 特点:
# 1.函数内部引用变量,会优先引用最近局部变量
# 2.具有逐级向上引用的特性
#%%
lemon = 5
def fruit_1():
#lemon = 10
print(lemon)
fruit_1()
运行结果:5
#%%
banana = 5
def fruit_1():
banana = 10
def fruit_2():
banana = 15
print(banana)
fruit_2()
fruit_1()
运行结果:15
11.GLOBAL关键字
# 函数外部,一般情况下,不可引用局部变量
# 怎样才能让函数外部,引用函数内部局部变量
#%%
def fruit():
global lemon,pear
lemon = 5
pear = 10
fruit()
print(lemon,pear)
运行结果:5 10
#%%
# 使用global关键字,可声明该变量为全局变量
# 使用global关键字,可声明多个全局变量
# 疑问:可否使用global关键字,给全局变量重新赋值
banana = 5
def fruit():
global banana
banana = 10
print('函数内部的banana为:' + str(banana))
fruit()
print('全局的banana为:' + str(banana))
运行结果:
函数内部的banana为:10 全局的banana为:10
# 总结:
# 1.使用 global关键字,可声明多个局部变量为全局变量
# 2.使用 global关键字,可以给全局变量重新赋值
12.函数RETURN的用法
# 程序运行第一个return语句后,大多数情况下,会跳出该函数,不再执行之后代码
# try excepy finally
#%%
def test():
a = 1
return a
print('hello lemon')
test()
运行结果:1
#%%
# 函数内,可存在多个return,一般与if 条件搭配
def test1(x,y):
if x > y:
return x
elif x < y:
return y
else:
return x + y
test1(4,5)
运行结果:5
#%%
def test1(x,y):
if x > y:
return x
elif x < y:
return y
return x + y
test1(4,3)
运行结果:4
#%%
# 当前面条件都不成立的时候,return x + y
# 减少代码数量,代码简洁
# 减少嵌套,易阅读
# return 支持返回多个结果
def fruit(lemon,apple):
lemon = lemon * 2
apple = apple * 2
return lemon,apple
fruit(4,5)
运行结果:(8,10)
#%%
def fruit(lemon,apple):
lemon = lemon * 2
apple = apple * 2
return lemon
return apple # 如果这样写,不会返回apple的值
fruit(4,5)
运行结果:8
# 建议:
# 接收的变量名命名,最好取一个方便记忆的名字
13. 案例:斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列。
因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。
1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 ……
这个数列从第3项开始,每一项都等于前两项之和。
在数学上,斐波纳契数列以如下被以递推的方法定义:
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
# 需求:创建一个函数,用户输入任意数字,返回第N项数字
#%%
def fib(num):
if num <=0:
raise Exception('数字要大于0')
if num == 1 or num == 2:
return 1
return fib(num -1) + fib(num-2)
fib(5)
运行结果:5
#%%
# 优化:
# 当 n <=0 的时候,需要中断程序,并告知用户错误原因
# 扩展:将第一项到第N项结果,存为一个列表
# 列表推导式
# [循环变量名 for 循环变量名 in 可迭代对象 if 条件判断]
#%%
a = []
for i in range(10):
a.append(i)
a
运行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#%%
b = [i for i in range(10) if i >5]
b
运行结果:
[6, 7, 8, 9]
#%%
num = int(input('请输入数字:'))
fibs_list = [fib(i) for i in range(1,num+1)]
fibs_list
运行结果:
请输入数字:6
[1, 1, 2, 3, 5, 8]
posted on 2020-10-23 00:16 kunlungege 阅读(259) 评论(0) 编辑 收藏 举报