函数先定义函数,后调用
一、定义函数:
1、简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
2、语法
Python 定义函数使用 def 关键字
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
1
2
3
4
5
6
7
8
9
10
|
def 函数名(param1,param2……): """ 函数功能的描述信息 :param1:描述 :param2:描述 :return:返回值 """ code ... return 返回值 |
3、无参函数
1
2
3
4
5
6
7
8
|
def register(): """注册功能""" username = input ( 'username: ' ).strip() pwd = input ( 'password: ' ).strip() with open ( '32.txt' , 'a' , encoding = 'utf8' ) as fa: fa.write(f "{username}:{pwd}\n" ) fa.flush() |
4、有参函数
1
2
3
4
5
6
|
def sum_self(x, y): """求和""" res = x + y print (res) sum_self( 1 , 2 ) # 3 |
5、空函数
你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数
1
2
|
def func(): pass |
二、调用函数及返回值
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
1
|
函数名(param1、param2……) |
如:
1
|
register() |
1、函数运行完毕所有代码,如果函数体不写return,则会返回None。
1
2
3
4
|
def foo(): pass print (foo()) #None |
2、函数可以返回一个或多个值(元组类型)
1
2
3
4
5
6
7
8
9
|
def func(): name = 'nick' age = 19 hobby_list = [ 'read' , 'run' ] return name, age, hobby_list name, age, hobby_list = func() print (name,age,hobby_list) #('nick', 19, ['read', 'run']) |
三、函数的参数
1、普通参数,位置必需参数
在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参。
特点:按照位置定义的形参,都必须被传值,多一个不行,少一个也不行。
1
2
3
|
def func(x, y): print (x) print (y) |
在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参。
特点:按照位置为对应的形参依次传值。
1
|
func( 1 , 2 ) |
2、关键字参数
在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参。
特点:可以打破位置的限制,但仍能为指定的形参赋值。
1
|
func(y = 2 , x = 1 ) |
- 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
- 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
1
2
3
|
func(x, y = 2 ) func(y = 2 , x) # SyntaxError: positional argument follows keyword argument func(x, x = 1 ) # NameError: name 'x' is not defined |
3、默认参数
在定义阶段,就已经被赋值。意味着在调用时可以不用为其赋值。位置形参必须放在默认形参的左边。
1
2
3
4
5
|
def func(x, y = 10 ): print (x) print (y) func( 2 ) |
默认形参的值只在定义阶段赋值一次,也就是说默认参数的值在函数定义阶段就已经固定了。
1
2
3
4
5
6
7
|
m = 10 def foo(x = m): print (x) m = 111 foo() # 10 |
默认参数的值通常应该是不可变类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def register(name, hobby, hobby_list = None ): hobby_list = [hobby] print (f "{name} prefer {hobby_list}" ) register( 'nick' , 'read' ) # ['read'] register( 'tank' , 'zuipao' ) # [ 'zuipao'] register( 'jason' , 'piao' ) # ['piao'] # 演示形参是可变类型,(列表是可变类型) def register(name, hobby, hobby_list = None ): hobby_list = [hobby] print (f "{name} prefer {hobby_list}" ) register( 'nick' , 'read' ) # nick prefer ['read'] register( 'tank' , 'zuipao' ) # tank prefer ['zuipao'] register( 'jason' , 'piao' ) # jason prefer ['piao']o'] |
4、不定长参数之*
形参中的*会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给*后的参数。需要注意的是:*后的参数名约定俗成为args。
1
2
3
4
5
6
7
8
9
|
def sum_self( * args): res = 0 for num in args: res + = num return res res = sum_self( 1 , 2 , 3 , 4 ) print (res) # 10 |
注意:实参之*
实参中的*,*会将*后参数的值循环取出,打散成位置实参。以后但凡碰到实参中带*的,它就是位置实参,应该马上打散成位置实参去看。
1
2
3
4
5
|
def func(x, y, z, * args): print (x, y, z, args) func( 1 , * ( 1 , 2 ) , 3 , 4 ) # 1 1 2 (3, 4) |
5、不定长参数之**
形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的参数。需要注意的是:**后的参数名约定俗成为kwargs。
1
2
3
4
5
|
def func( * * kwargw): print (kwargw) func(a = 5 ,b = 3 ) # {'a': 5, 'b': 3} |
注意:实参之**
实参中的**,**会将**后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。
1
2
3
4
5
|
def func(x, y, z, * * kwargs): print (x, y, z, kwargs) func( 1 , 3 , 4 , * * { 'a' : 1 , 'b' : 2 } ) # 1 3 4 {'a': 1, 'b': 2} |
可变长参数应用
1
2
3
4
5
6
7
8
9
10
11
|
def index(name, age, sex): print (f "name: {name}, age: {age}, sex: {sex}" ) # name: nick, age: 19, sex: male def wrapper( * args, * * kwargs): print (f "args: {args}" ) # args: () print (f "kwargs: {kwargs}" ) # kwargs: {'name': 'nick', 'sex': 'male', 'age': 19} index( * args, * * kwargs) wrapper(name = 'nick' , sex = 'male' , age = 19 ) |
6、命名关键字参数
命名关键字则是在「位置参数」和「命名关键字参数」中使用,*,隔开,后面的即为命名关键字。* 后的参数必须用关键字传入。
1
2
3
4
5
6
|
def student(name, age, * , city, gender): print (name, age, city, gender) student( 'xiaoming' , 6 , city = 'beijing' , gender = 'male' ) # xiaoming 6 beijing male student( 'xiaoming' , 6 , 'beijing' , 'male' ) #TypeError: student() takes 2 positional arguments but 4 were given |
特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。
1
2
3
4
5
6
7
|
def register(x, y, * , name, gender = 'male' , age): print (x) print (name) print (age) register( 1 , 2 , name1 = 'nick' , age = 19 ) # TypeError: register() got an unexpected keyword argument 'name1' |
Python3.8 新增了一个函数形参语法, “/” 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:
1
2
|
def f(a, b, / , c, d, * , e, f): print (a, b, c, d, e, f) |
以下使用方法是正确的:
1
|
f( 10 , 20 , 30 , d = 40 , e = 50 , f = 60 ) |
四、函数对象
函数是第一类对象,即函数可以被当做数据处理。
1
2
3
4
5
|
def func(): print ( 'from func' ) print (func) # |
1、函数当作参数传给一个另一函数
1
2
3
4
5
6
7
8
9
|
def func(): print ( 'from func' ) def foo(m): m() foo(func) # from func |
2、函数当作另一函数的返回值
1
2
3
4
5
6
7
8
9
10
|
def func(): print ( 'from func' ) def foo(x): return x res = foo(func) print (res) # |
3、函数可以当作容器类型的元素
1
2
3
4
5
6
|
def func(): print ( 'from func' ) function_list = [func] function_list[ 0 ]() # from func |
五、函数递归
递归的精髓在于通过不断地重复逼近一个最终的结果。
age(1)=26,age(n)=age(n-1)+2 ,求age(5)的值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
''' ... age(5) = age(4) + 2 age(4) = age(3) + 2 age(3) = age(2) + 2 age(2) = age(1) + 2 age(1) = 26 age(n) = age(n-1) +2 age(1) = 26 # n=1 ''' def age(n): if n = = 1 : return 26 res = age(n - 1 ) + 2 return res print (f "age(5): {age(5)}" ) |
递归的本质就是干重复的活。
1
2
3
4
5
6
7
8
9
10
11
12
|
lis = [ 1 , [ 2 , [ 3 , [ 4 , [ 5 , [ 6 , ]]]]]] def tell(lis): for i in lis: if type (i) is list : tell(i) else : print (i) tell(lis) |
二分法的思想实现查找数字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
from random import randint nums = [randint( 1 , 100 ) for i in range ( 100 )] nums = sorted (nums) def search(search_num, nums): print (nums) mid_index = len (nums) / / 2 if not nums: print ( 'not exists' ) return if search_num > nums[mid_index]: # in the right nums = nums[mid_index + 1 :] search(search_num, nums) elif search_num < nums[mid_index]: # in the left nums = nums[:mid_index] search(search_num, nums) else : print ( 'find it' ) search( 7 , nums) |
六、匿名函数:
python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
1、语法
lamdbda 参数 : 逻辑代码
1
2
3
4
5
6
|
# 可写函数说明 sum = lambda arg1, arg2: arg1 + arg2 # 调用sum函数 print ( "相加后的值为 : " , sum ( 10 , 20 )) print ( "相加后的值为 : " , sum ( 20 , 20 )) |
匿名函数,他没有绑定名字,使用一次即被收回,加括号既可以运行。
1
2
3
|
print ( lambda x, y: x + y ) # (x, y)> res = ( lambda x, y: x + y)( 1 , 2 ) print (res) # 3 |
lambda 匿名函数也是可以使用"关键字参数"进行参数传递,也可以设定默认值。
1
2
3
4
5
6
7
|
g = lambda x = 0 , y = 0 : x * * 2 + y * * 2 print (g( 2 , 3 )) # 13 print (g( 2 )) # 4 print (g(y = 3 )) # 9 |
2、与内置函数联用
匿名函数通常与max()、sorted()、filter()、sorted()方法联用。
1.max()
如果我们想从上述字典中取出薪资最高的人,我们可以使用max()方法,但是max()默认比较的是字典的key。
- 首先将可迭代对象变成迭代器对象
- res=next(迭代器对象),将res当做参数传给key指定的函数,然后将该函数的返回值当做判断依据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
salary_dict = { 'nick' : 3000 , 'jason' : 100000 , 'tank' : 5000 , 'sean' : 2000 } print ( max (salary_dict)) # tank def func(k): return salary_dict[k] print ( max (salary_dict, key = func)) # jason print ( max (salary_dict, key = lambda name: salary_dict[name] ) ) # jason 匿名函数 |
2.sorted()
如果我们想对上述字典中的人,按照薪资从大到小排序,可以使用sorted()方法。
- 首先将可迭代对象变成迭代器对象
- res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值当做判断依据。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
lis = [ 1 , 3 , 2 , 5 , 8 , 6 ] sorted (lis) print (lis) # [1, 3, 2, 5, 8, 6] print ( sorted (lis, reverse = True )) # [8, 6, 5, 3, 2, 1] salary_dict = { 'nick' : 3000 , 'jason' : 100000 , 'tank' : 5000 , 'sean' : 2000 } print ( sorted (salary_dict, key = lambda name: salary_dict[name] )) # ['sean', 'nick', 'tank', 'jason'] |
3.map()
如果我们想对一个列表中的某个人名做处理,可以使用map()方法。
- 首先将可迭代对象变成迭代器对象
- res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后将该函数的返回值作为map()方法的结果之一。
1
2
3
4
|
name_list = [ 'jason' , 'tank' , 'sean' ] res = map ( lambda name: f "{name} sb" , name_list) print ( list (res)) # ['jason sb', 'tank sb', 'sean sb'] |
4.filter()
如果我们想筛选除名字中含有'sb'的名字,我们可以使用filter()方法。
- 首先将可迭代对象变成迭代器对象
- res=next(迭代器对象),将res当做参数传给第一个参数指定的函数,然后filter会判断函数的返回值的真假,如果为真则留下。
1
2
3
4
|
name_list = [ 'nick' , 'jason sb' , 'tank sb' , 'sean sb' ] filter_res = filter ( lambda name: name.endswith( 'sb' ), name_list) print ( list (filter_res)) # ['jason sb', 'tank sb', 'sean sb'] |
七、内置函数
共68个:
abs()、 all()、 any()、 ascii()、 bin()、 bool()、 bytearray()、 bytes()、 callable()、 chr()、 classmethod()、 compile()、 complex()、 delattr()、
dict()、 dir()、 divmod()、 enumerate()、 eval()、 exec()、 filter()、 float()、 format()、 frozenset()、 getattr()、 globals()、 hasattr()、 hash()、
help()、 hex()、 id()、 input()、 int()、 isinstance()、 issubclass()、 iter()、 len()、 list()、 locals()、 map()、 max()、 memoryview()、
min()、 next()、 object()、 oct()、 open()、 ord()、 pow()、 print()、 property()、 range()、 repr()、 reversed()、 round()、 set()、
setattr()、 slice()、 sorted()、 staticmethod()、 str()、 sum()、 super()、 tuple()、 type()、 vars()、 zip()、 __import__()、
1.bytes():解码字符。
1
2
3
4
|
res = '你好' .encode( 'utf8' ) print (res) # b'\xe4\xbd\xa0\xe5\xa5\xbd' res = bytes( '你好' , encoding = 'utf8' ) print (res) # b'\xe4\xbd\xa0\xe5\xa5\xbd' |
2.chr()/ord():chr()参考ASCII码表将数字转成对应字符;ord()将字符转换成对应的数字。
1
2
|
print ( chr ( 65 )) #A print ( ord ( 'A' )) #65 |
3.divmod():分栏。
1
|
print ( divmod ( 10 , 3 )) #(3, 1) |
4.enumerate():带有索引的迭代。
1
2
3
4
5
6
7
|
l = [ 'a' , 'b' , 'c' ] for i in enumerate (l): print (i) # (0, 'a') # (1, 'b') # (2, 'c') |
5.eval():把字符串翻译成数据类型。
1
2
3
|
lis = '[1,2,3]' lis_eval = eval (lis) print (lis_eval) #[1, 2, 3] |
6.hash():是否可哈希。
1
|
print ( hash ( 1 )) #1 |
7.abs():求绝对值。
1
|
print ( abs ( - 13 )) # 13 |
8.all():可迭代对象内元素全为真,则返回真。
1
2
|
print ( all ([ 1 , 2 , 3 , 0 ])) #False print ( all ([])) #True |
9.any():可迭代对象中有一元素为真,则为真。
1
2
|
print ( any ([ 1 , 2 , 3 , 0 ])) #True print ( any ([])) #False |
10.bin()/oct()/hex():二进制、八进制、十六进制转换。
1
2
3
|
print ( bin ( 17 )) #0b10001 print ( oct ( 17 )) #0o21 print ( hex ( 17 )) #0x11 |
11.dir():列举出所有time的功能。
1
2
3
|
import time print ( dir (time)) # ['_STRUCT_TM_ITEMS', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset'] |
12.frozenset():不可变集合。
1
2
|
s = frozenset ({ 1 , 2 , 3 }) print (s) #({1, 2, 3}) |
13.globals()/loacals():查看全局名字;查看局部名字。
1
2
3
4
5
6
7
8
|
# print(globals()) def func(): a = 1 # print(globals()) print ( locals ()) func() # {'a': 1} |
14.pow():
1
|
print ( pow ( 3 , 2 , 3 )) # (3**2)%3 =0 |
15.round():
1
|
print ( round ( 3.5 )) #4 |
16.slice():
1
2
3
4
|
lis = [ 'a' , 'b' , 'c' ] s = slice ( 1 , 4 , 1 ) print (lis[s]) #['b', 'c'] # print(lis[1:4:1]) |
17.sum():
1
|
print ( sum ( range ( 100 ))) #4950 |
18.__import__():通过字符串导入模块。
1
2
|
m = __import__ ( 'time' ) print (m.time()) #1556607502.334777 |
19. 面向对象知识点
- classmethod
- staticmethod
- property
- delattr
- hasattr
- getattr
- setattr
- isinstance()
- issubclass()
- object()
- super()
到此这篇关于Python函数的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/springsnow/p/11912755.html