函数
引子:
求1-15的和;
求23-36的和;
求55-68的和;
i1 = int(input('i1:'))
i2 = int(input('i2:'))
def sum_of_num(i1, i2):
result = 0
for i in range(i1, i2+1):
result += i
return result
print(sum_of_num(i1, i2))
对于程序而言:函数就是对程序逻辑进行结构化或者进程化的一种编程方法
内置函数:built-in function —> BIF
函数的定于
声明函数的一般形式:
def function_name(arg1, arg2, ..., argn):
''' statements'''
func_statements
return Value
说明如下:
1.函数代码块以 def 关键词开头,后接函数标识符名称和小括号 ()。
2.任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
3.函数的第一行语句可以选择性地使用文档字符串----用于存放函数说明。
4.函数内容以冒号起始,并且缩进。
5.return [表达式] 结束函数,选择性的返回一个值给调用方。不带表达式的return相当于返回 None。
其中参数列表和返回值不是必须的,return后也可以不跟返回值,甚至连 return也没有。
对于return后没有返回值的和没有return语句的函数都会返回None值
有些函数可能既不需要传递参数,也没有返回值。
没有参数时,包含参数的圆括号也必须写上,圆括号后也必须有“:”。
函数调用
函数文档说明
函数参数
- 不传参函数
- 参数函数
- 顺序
函数返回值
函数参数种类
形参和实参
def info(name, age):
info = {'name': name, 'age': age}
return info
print(info('City', 1999))
def usr_manege(name, age, job, hobby = 'Trip'):
print('用户管理系统'.center(16, '-'))
print('\tName:\t', name)
print('\tAge:\t', age)
print('\tJob:\t', job)
print('\tHobby:\t', hobby)
print('用户管理系统'.center(16, '-'))
usr_manege('Jack', 21, 'IT')
usr_manege('Tom', 20, 'IT', 'Coding')
usr_manege('Joe', 18, 'Student', 'Reading')
-----用户管理系统-----
Name: Jack
Age: 21
Job: IT
Hobby: Trip
-----用户管理系统-----
-----用户管理系统-----
Name: Tom
Age: 20
Job: IT
Hobby: Coding
-----用户管理系统-----
-----用户管理系统-----
Name: Joe
Age: 18
Job: Student
Hobby: Reading
-----用户管理系统-----
只传递实参,位置一一对应 —> 位置参数
使用位置参数时和函数头定义的形参在顺序,个数以及类型上匹配
关键字参数
def usr_manege(name, age, job = 'IT', hobby = 'Trip'):
print('用户管理系统'.center(16, '-'))
print('\tName:\t', name)
print('\tAge:\t', age)
print('\tJob:\t', job)
print('\tHobby:\t', hobby)
print('用户管理系统'.center(16, '-'))
usr_manege('Jack', hobby='Coding', job='Student')
usr_manege('Tom', 20, 'IT', 'Coding')
usr_manege('Joe', 18, 'Student', 'Reading')
默认值参数,关键字参数,必须放置于位置参数之后
不定参数
在Python中不定参数主要是指 *args 和 **kwargs 两个魔法变量
他们俩主要是用于函数定义,我们可以将不定数量的参数传递给一个函数
- *args 用来接收任意非键值对的任意数量的参数列表给函数
def uncertain_para(para, para2, *args):
print('普通位置参数:', para, para2)
print('不定参数:', args)
print(type(args))
uncertain_para(1, 2, 3, 4, 'a', 'b')
uncertain_para([1, 2, 3], 'ab', 'cd', 'ef')
普通位置参数: 1 2
不定参数: (3, 4, 'a', 'b')
<class 'tuple'>
普通位置参数: [1, 2, 3] ab
不定参数: ('cd', 'ef')
<class 'tuple'>
def avg(*a):
s = 0
for i in a:
s += i
return s/len(a)
print(avg(1, 2, 3))
print(avg(2, 3, 4, 5, 6))
- **kwargs 用来接收任意不定长度的键值对列表给函数
def un_para_key(**kwargs):
print(kwargs)
print(type(kwargs))
un_para_key(a=1, b=2, c=3, d=5)
{'a': 1, 'b': 2, 'c': 3, 'd': 5}
<class 'dict'>
写一个函数,计算传入字符中的数字、字母、空格、其他的个数
def func(p):
digital = 0
alpha = 0
space = 0
others = 0
for i in p:
if i.isdigit():
digital += 1
elif i.isalpha():
alpha += 1
elif i.isspace():
space += 1
else:
others += 1
return digital, alpha, space, others
print(func('asds516 asa #'))
函数引用
def foo():
print('in foo()')
bar()
def bar():
print('in bar()')
foo()
你可以获得每个 pyhon 模块,类,和函数中任意的名字空间。你可以在模块 foo 和 bar 里都有名为 x 的一个变量,,但是在将这两个模块导入你的程序后,仍然可以使用这两个变量。所以,即使在两个模块中使用了相同的变量名字,这也是安全的,因为句点属性标识对于两个模块意味了不同的命名空间,比如说,在这段代码中没有名字冲突:
函数属性
函数属性时Python中另外一个使用了句点属性标识并拥有名字空间的领域
def foo():
'foo() --- Properly created doc string.'
def bar():
pass
bar.__doc__ = 'Oops, forget the doc str above'
bar.version = 0.1
内嵌函数
作用域
bar()整个函数都处于外部fool()函数的作用域里(foo()是我们可以从外部访问的一个对象区域)。除了在foo()内部
def foo():
def bar():
print('bar() called.')
print('foo() called.')
bar()
foo()
bar()
# bar()
# NameError: name 'bar' is not defined
变量作用域
就作用域而言,python和C有很大差别,只有当变量在module,Class,函数中定义的时候,才会有作用域的概念。
def foo():
a = 'foo'
print(a)
foo()
print(a)
在作用域中定义的变量,一般只在作用域内有效。需要注意的是,在if - else,for - else,while - else,try - except(else - finally)等关键字的语句块中不会产生作用域。
作用域的类型
Python中,使用一个变量时并不要求需要预先声明它。但在真正使用的时候,他必须绑定到某个内存对象(被定义,赋值)。这种变量名的绑定将在当前作用域引入新的变量,同时,屏蔽外层作用域中的同名变量。
-
局部作用域(locale – L)
- 局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。
- 局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
-
嵌套作用域(enclosing – E)
- E 也包含在def关键字中,E和L时相对的,E相对于更上层的函数而言也是一个局部作用域。于L的区别在于,对于一个函数而言,L是定义在此函数内部的局部作用域。
- 主要为了实现Python的闭包,而增加的实现
-
全局作用域(Global – G)
- 即在模块层次中定义的变量。模块顶层申明的变量具有全局作用域。从外部来看,模块的全局变量就是一个模块对象的属性。
-
内置作用域(built - in – B)
- 系统固定模块中定义的变量
搜索变量名的优先级:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域。
全部变量和局部变量
gb1_str = 'foo'
def foo():
loc_str = 'bar'
return gb1_str + loc_str
print(foo())
print(gb1_str)
a = 6688
def foo():
a = 666
print('foo(),修改前a:\t', a)
a = 888
print('foo(),修改后a:\t', a)
def bar():
a = 6688
print('bar(),a:\t', a)
foo()
bar()
foo(),修改前a: 666
foo(),修改后a: 888
bar(),a: 6688
a = 6688
def foo():
global a
print('foo(),修改前a:\t', a)
a = 666
print('foo(),修改前a:\t', a)
def bar():
print('bar(), a:\t', a)
foo()
bar()
foo(),修改前a: 6688
foo(),修改前a: 666
bar(), a: 666
a = 6688
def foo():
a = 666
def inner_foo():
global a
print('inner_foo(), change_before:\t', a)
a = 888
print('inner_foo(),change_after:\t', a)
inner_foo()
print('foo(), a\t', a)
print(a)
foo()
print(a)
6688
inner_foo(), change_before: 6688
inner_foo(),change_after: 888
foo(), a 666
888