函数参数
只有一个参数名,称作位置参数
参数形式时key=value,称作关键字参数
>>> def get_age(name, age):
... print('%s is %s years old' % (name, age))
...
>>> get_age('bob', 20)
bob is 20 years old
>>> get_age() #Error,参数太少
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: get_age() missing 2 required positional arguments: 'name' and 'age'
>>> get_age('bob', 20, 100) #Error,参数太多
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: get_age() takes 2 positional arguments but 3 were given
>>> get_age(20, 'bob') #语法正确,但是语义错误
20 is bob years old
>>> get_age(age=20, name= 'bob') #ok
bob is 20 years old
>>> get_age(age=20, 'bob') #Error,关键字参数必须在后
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> get_age(20, name= 'bob') #Error,name得到了多个值
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: get_age() got multiple values for argument 'name'
>>> get_age('bob', age=20) #ok
bob is 20 years old
参数组
如果函数的参数个数是不固定的,可以使用参数组接收参数
• python允许程序员执行一个没有显式定义参数的函数
• 相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数组传递给函数
— 在参数名前加"*“表示参数是元组
— 在参数名前加”**"表示参数是字典
>>> def func1(*args):
... print(args)
...
>>> func1()
()
>>> func1('bob')
('bob',)
>>> func1('bob', 123, 'hello', 'aaa')
('bob', 123, 'hello', 'aaa')
>>> def func2(**args):
... print(args)
...
>>> func2()
{}
>>> func2(name ='bob', age=20)
{'name': 'bob', 'age': 20}
调用函数时,如果参数有“*”,表示把参数拆开
>>> def add(x, y):
... print(x+y)
...
>>> nums = [10, 20]
>>> num_dict = {'x': 10, 'y': 20}
>>> num_dict2 = {'a': 10, 'b': 20}
>>> add(nums) #Error,参数nums赋值给了x,y没有得到值
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'y'
>>> add(num_dict) #Error,参数nums赋值给了x,y没有得到值
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'y'
>>> add(*nums) # nums拆成了10, 20
30
>>> add(**num_dict) # 拆成了x=100, y=200
30
>>> add(**num_dict2) # 拆成了a=100, b=200,与函数定义的形参名不符
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() got an unexpected keyword argument 'a'
匿名函数
—如果函数的代码块非常简单,只有一行,可以使用匿名函数。
—匿名函数使用lambda关键字定义。
>>> def add(x, y):
... return x + y
...
>>> add(10, 20)
30
>>> myadd = lambda x, y: x + y
>>> myadd(10, 20)
30
[root@room9pc01 day07]# vim math_game3.py
from random import randint, choice
def exam():
cmds = {'+': lambda x, y: x + y, '-': lambda x, y: x-y} #使用匿名函数传值
nums = [randint(1, 100) for i in range(2)]
nums.sort(reverse = True) #降序排列
op = choice('+-')
result = cmds[op](*nums)
prompt ='%s %s %s = ' % (nums[-2], op, nums[-1])
counter = 0
while counter < 3:
try:
answer = int(input(prompt))
except: #不指定异常默认捕获所有异常,但是不推荐
print()
continue
if answer == result:
print('Very Good!')
break
print('Answer Wrong !')
counter += 1
else:
print('%s %s' % (prompt, result))
if __name__ == '__main__':
while True:
exam()
try:
yn = input('Continue(y/n)? ').strip()[0] #删除用户输入的多余空格,并取出第一个字符
except IndexError:
yn = 'y'
except (KeyboardInterrupt, EOFError):
yn = 'n'
if yn in 'nN':
print('\nBye-bye')
break
filter和map函数
[root@room9pc01 day07]# vim filter_func.py
ffrom random import randint
def func1(x):
return True if x > 50 else False
def func2(x):
return x +2
if __name__ == '__main__':
nums = [randint(1,100) for i in range(10)]
print(nums)
result =filter(func1, nums)
print(list(result))
result2 = filter(lambda x: True if x > 50 else False, nums)
print(list(result2))
result3 = map(func2, nums)
print(list(result3))
result4 = map(lambda x: x+2, nums)
print(list(result4))
[root@room9pc01 day07]# python3 filter_func.py
[34, 3, 74, 31, 94, 81, 38, 13, 20, 57]
[74, 94, 81, 57]
[74, 94, 81, 57]
[36, 5, 76, 33, 96, 83, 40, 15, 22, 59]
[36, 5, 76, 33, 96, 83, 40, 15, 22, 59]
filter和map函数赋值时只能使用一次
>>> nums = filter(lambda x: x%2==0, [i for i in range(10)])
>>> nums
<filter object at 0x7fd566ab3668> #filter函数对象
>>> list(nums)
[0, 2, 4, 6, 8]
>>> list(nums)
[]
>>> nums = map(lambda x: x+2, [i for i in range(10)])
>>> nums
<map object at 0x7fd566ab3668> #map函数对象
>>> list(nums)
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> list(nums)
[]
>>> nums = map(lambda x: x+2, [i for i in range(10)])
>>> ab =list(nums)
>>> ab
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> ab
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> abc= list(nums)
>>> abc
[]
全局变量
在函数外面定义的变量。从定义起始位置开始,一直到程序结束,任何地方均可见可用。
局部变量
在函数内部定义的变量。只在函数内部使用,离开函数不能使用。函数的参数也可以看作是局部变量。
>>> x = 10 #x为全局变量
>>> def func1():
... print(x)
...
>>> func1()
10
>>> def func2():
... x = 'hello' #x为局部变量,局部和全局有相同的变量,局部遮盖住全局变量
... print(x)
...
>>> func2()
hello
>>> x
10
>>> def func3():
... global x # 声明函数内部使用的是全局变量x
... x = 'ni hao'
... print(x)
...
>>> func3()
ni hao
>>> x
'ni hao'
名称查找的时候,先查局部,再查全局,最后查内建。
>>> def func4():
... print(len('abc'))
...
>>> func4() #查到了内建len函数
3
>>> len = 10
>>> func4() #在全局查到len的值是10,数字不能调用
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in func4
TypeError: 'int' object is not callable
partial偏函数
>>> from functools import partial
>> add(10, 20, 30, 40, 50)
150
>>> add(10, 20, 30, 40, 9)
109
>>> add(10, 20, 30, 40, 15)
115
>>> myadd = partial(add, 10, 20, 30, 40)
>>> myadd(50)
150
>>> myadd(9)
109
>>> myadd(15)
115
案例:简单GUI程序
[root@room9pc01 day07]# vim mygui.py //编写gui程序
import tkinter
from functools import partial
window = tkinter.Tk()
lb = tkinter.Label(window, text = 'Hello World', font= 'Arial 20')
#b1 = tkinter.Button(window, fg='white', bg='blue', text='Button 1')
#b2 = tkinter.Button(window, fg='white', bg='blue', text='Button 2')
#b3 = tkinter.Button(window, fg='white', bg='blue', text='quit', command=window.quit)
MyButton = partial(tkinter.Button, window, fg='white', bg='blue')
b1 = MyButton(text='Button 1')
b2 = MyButton(text='Button 1')
b3 = MyButton(text='quit', command=window.quit)
lb.pack()
b1.pack()
b2.pack()
b3.pack()
window.mainloop()
递归函数
• 如果函数包含了对其自身的调用,该函数就是递归的
• 在操作系统中,查看某一目录内所有文件、修改权限等都是递归的应用
[root@room9pc01 day07]# vim fun_jiecheng.py //阶乘程序计算n!
def func(n):
if n == 1:
return 1
return n*func(n-1)
if __name__ == '__main__':
print(func(5))
[root@room9pc01 day07]# python3 fun_jiecheng.py //计算5的阶乘5!
120
快速排序:
假定第一个数是中间值。把比这个数小的放到smaller列表,把比它大的数放到larger列表。最后把这三个部分拼接起来。smaller和larger采用相同的办法继续排序,直到列表的长度是0或1结束。
[root@room9pc01 day07]# vim qsort.py //编写程序,在1—100之间随机取10个数,并按从小到大顺序排序
from random import randint
def qsort(seq):
if len(seq) < 2: #如果长度小于2,不用排序,直接返回
return seq
middle = seq[0] #假定第一个值是中间值
smaller = [] #用于保存比中间值小的数据
larger = [] #用于保存比中间值大的数据
for i in seq[1:]:
if i < middle:
smaller.append(i)
else:
larger.append(i)
return qsort(smaller) + [middle] +qsort(larger)
if __name__ == '__main__':
nums = [randint(1, 100) for i in range(10)]
print(nums)
print(qsort(nums))
[root@room9pc01 day07]# python3 qsort.py //程序演示
[44, 96, 7, 52, 76, 35, 10, 55, 68, 76]
[7, 10, 35, 44, 52, 55, 68, 76, 76, 96]
生成器
- 生成器本质上也是函数。和普通函数不同,普通函数只能通过return返回一个值,但是生成器可以通过yield返回多个中间值。
- 生成器对象只能使用一次。
>>> def mygen(): #定义生成器函数
... yield 'hello' #生成器函数通过yield返回值
... yield 50
... yield 'a+b'
... a = 10 + 20
... yield a
...
>>> mg = mygen()
>>> mg
<generator object mygen at 0x7fd56e22cbf8>
>>> list(mg) #将生成器对象转换为列表
['hello', 50, 'a+b', 30]
>>> list(mg) #生成器对象只能使用一次
[]
>>> mga = mygen() #通过赋值值生成器函数,可以重复获取生成器对象
>>> mga
<generator object mygen at 0x7fd56e22cc50> #表明为生成器对象,占用内存空间小
>>> list(mga)
['hello', 50, 'a+b', 30]
>>> for i in mga: #上一条命令使用了一次生成器对象,无法遍历
... print(i)
...
>>> mga = mygen()
>>> for i in mga: #重新赋值生成器对象,for循环可以遍历
... print(i)
...
hello
50
a+b
30
生成器还可以使用生成器表达式
>>> from random import randint
>>> nums = (randint(1, 100) for i in range(10)) #生成器表达式
>>> nums
<generator object <genexpr> at 0x7fd566a8feb8> #生成器对象
>>> list(nums)
[5, 17, 84, 16, 22, 4, 48, 22, 87, 67]
>>> list(nums)
[]
>>> ips = ('192.168.8.%s' % i for i in range(1, 5))
>>> ips
<generator object <genexpr> at 0x7fd566a8ffc0> #生成器对象
>>> for ip in ips:
... print(ip)
...
192.168.8.1
192.168.8.2
192.168.8.3
192.168.8.4