⑥可变长参数(2种)

1.位置可变长参数         *args       函数里面(元组)

2.关键字可变长参数    ** args     函数里面得到的是{字典}

 

*names-位置可变长参数 :在函数内部的表现形式:names是一个元组

def get_name(firstname,*names):
    print(firstname)
    print(names)
    return firstname
print(get_name('lemon')) #调用函数时,可变长参数没有传入参数,就是一个空元组
#lemon
()
lemon

1.可以接收从函数调用的时候,多余的位置参数

def get_name(firstname,*names):
    print(firstname)
    print(names)
    return firstname
print(get_name('lemon','python','good')) #多余的位置参数,被*names全部接收

"""
lemon
('python', 'good')
lemon
"""

2.*name必须加在其他的位置参数的后面---------位置参数是大佬(否则会报错)

一般写成*args,但是不是一定要写成*args,只是个占坑的,可以随便换可变长参数的名字,只要有意义就行。

3.可不可以只有一个可变长参数?当然可以,调用函数时传入的参数全部被*names接收

#只有一个可变长参数
def get_name(*names):
    return names
print(get_name('lemon','python','good'))

"""
('lemon', 'python', 'good')
"""

4.可不可以有多个可变长参数?不可以!没有必要,有一个就可以收走全部剩余的位置参数了

 

 

**kwargs--关键字可变长参数(keyword argument)

1.调用函数时**kwargs不传入参数,返回的是空字典{}

#调用函数不传入关键字参数
def get_name(*names,**kwargs):
    '''获取名字'''
    print(names)
    print(kwargs)
print(get_name('lemon','python','good')) 

"""
('lemon', 'python', 'good')
{}
None
"""

2.调用函数时**kwargs传入参数,返回的是字典{},以key-value形式存储

#调用函数传入关键字参数
def get_name(*names,**kwargs):
    '''获取名字'''
    print(names)
    print(kwargs)
print(get_name('lemon','python',teacher = 'yuz',age = '19')) 

"""
('lemon', 'python')
{'teacher': 'yuz', 'age': '19'}
None
"""

3.位置可变长参数*names 要放在关键字可变长参数**kwargs的前面

 

函数之间的调用

 先举个例子,内嵌函数的调用

def eat(name,food):
    print('{}喜欢吃的食物:{}'.format(name,food))

def congratulate(offer_name,money):
    '''庆祝拿到offer'''
    print('{}拿到了{}元的offer'.format(offer_name,money))
    eat(offer_name,'小龙虾')
congratulate('李同学',20)
'''
李同学拿到了20元的offer
李同学喜欢吃的食物:小龙虾
'''
#改变eat()函数的顺序
def congratulate(offer_name,money):
    '''庆祝拿到offer'''
    print('{}拿到了{}元的offer'.format(offer_name,money))
    eat(offer_name,'小龙虾')


def eat(name,food): print('{}喜欢吃的食物:{}'.format(name,food)) congratulate('李同学',20) ''' 李同学拿到了20元的offer 李同学喜欢吃的食物:小龙虾 '''

把eat()函数放在调用的后面再看看(报错,必须在调用的前面,否则找不到eat()函数,无法继续内嵌调用)

代码执行到congratulate('李同学',20)时,会跳到def congratulate(offer_name,money):函数体里面去执行,不会再去后面运行eat()函数,就是找不到eat()函数

def congratulate(offer_name,money):
    '''庆祝拿到offer'''
    print('{}拿到了{}元的offer'.format(offer_name,money))
    eat(offer_name,'小龙虾')

congratulate('李同学',20)

#eat()函数放在congratulate()调用的后面
def eat(name,food):
    print('{}喜欢吃的食物:{}'.format(name,food))
'''
李同学拿到了20元的offer
NameError: name 'eat' is not defined
'''

 

函数的作用域

1.函数的全局变量:整个文件都可以共用的,在函数体外面的

   函数的局部变量:在函数体这个局部里面

话不多说,上个例子,明白易懂

def add(a,b):
    c = a + b
    print('函数里面的c'.format(c))
    return c
c = 4
print('函数外面的c'.format(c))
add(5,8)
'''
函数外面的c
函数里面的c
'''
#先执行的是print('函数外面的c'.format(c)),再执行函数add()的调用

2.规律:全局能获取局部变量吗?--------不能!!

    局部作用域能获取全局变量吗?--------能!!

    全局能修改局部变量吗?-------不能!!!(全局不能获取局部变量,更不可能修改)

    局部作用域能修改全局变量吗?------能(前提是加global)

全部变量、局部变量的坑(容易出面试题)

1.全局作用域不能获取局部变量

defadd(a,b):
    c = a + b
    c += 5
    return c
c = 4
add(5,8)
print(c)#这里打印的是全部变量c,跟局部变量没有关系
'''
4
'''
def add(a,b):
    c = a + b
    c += 5
    return c
c = 4
c = add(5,8) #调用函数的结果给了全部变量c,c发生了变化
print(c)
'''
18
'''

2.局部作用域能获取全局变量

c = 8
def add(a,b):
  return a+b+c
print(add(2,4))
'''
14
'''

3.加global,在局部作用域修改全局变量

❤不加global 表明是全局变量,局部是不能修改全局变量的

  如果想在局部去修改全局变量,加global 表明这是一个全局变量

 

 

c = 4
def add(a,b):
    c = c + 4 # '='号前面的c是局部作用域的变量,'='号后面的c是全局变量,到底是局部变量还是全局变量,就搞不清楚了
print(c) return a+b+c add(2,4) #报错!!局部不能修改全局变量(在没有global关键字的时候)
#在局部作用域加global,将局部的c变成全局
c = 4
def add(a,b):
    global c
    c = c + 4
    print(c) 
add(2,4)
print('最后的c是{}'.format(c))
'''
8
最后的c是8
''

外部定义了列表类型的变量,在函数内部没有进行global声明,使用列表的方法增加了列表元素,最后发现外部的列表也被修改了,可以修改的数据类型在函数内部做修改操作是不需要声明global的,但是赋值就一定要声明global。 

 

 

总结:位置参数、默认参数、关键字参数混合在一起

1.位置参数一定是排在前面,默认参数、关键字参数放在后面(也就是没有=号的在前面,有=号的必须放在后面),否则就是错的。

2.函数的调用禁忌!!!!

①2个函数不要去相互调用,相互调用会导致递归错误,内存有限,一直循环,内存会爆掉。(recursionError:递归错误)

def get_money(date):
    get_name('pig','li')
    return '我再{}号讨薪资'.format(date)

def get_name(firstname,lastname):
    get_money(9)
    return firstname + lastname
print(get_money(9))

②函数不要自己调用自己,否则也会导致递归错误

def get_money(date):
    print('去讨薪')
    get_money(date)
    
print(get_money(8))#死循环

 

为什么要使用函数(函数的作用)-------存储一段代码、程序

1、当你发现你在复制、粘贴相同的或者类似的代码的时候,那么,极有可能你需要定义一个函数,会把同样的一段代码存储到函数当中-----→封装

封装成函数:把一段代码存储在函数中

封装成函数,重复利用一段代码的时候,只需要重复调用一个函数就可以了。

2.函数可不可以存储变量?不存储(变量一般是放在函数的外面),函数里面的是一个形式参数

实际参数被这样提取出来:如果想把一段代码封装成函数,里面有变量的值一直是变化的,就可以这个变量作为形式参数,放在函数里面。(函数一般是有参数的,也可以在参数里面用input动态的获取参数)

 

内置函数(69个)

①abs()  返回一个数的绝对值

②set()  集合的转化函数  去重

③dict() 字典的转化函数

④list() 列表的转化函数 

⑤max() 返回最大值的函数

⑥min() 返回最小值的函数

⑦sorted()对一个可迭代对象的排序(从小到大)

❤sort() 与sorted()对比------面试题

1.使用时表示不一样list1.sort()     sorted(list1)

2.是否修改原列表

sorted()返回的是一个新的列表,----sorted()有返回值,是个新的列表,原列表没有变化

lst = [1,4,7,2,9,8]
print(sorted(lst))
print(lst)
'''
[1, 2, 4, 7, 8, 9]
[1, 4, 7, 2, 9, 8]
'''

sort()----没有返回值,只是修改了原列表

lst = [1,4,7,2,9,8]
new_lst =
lst.sort()
print(new_lst)#sort()函数没有返回值
print(lst)

'''
None
[1, 2, 4, 7, 8, 9]
'''

 

⑧enumerate() 枚举 可以同时获取  索引,和对应的值,元组形式

lst = [1,5,3,7,8,2]
for i in enumerate(lst):
    print(i)
'''
(0, 1)
(1, 5)
(2, 3)
(3, 7)
(4, 8)
(5, 2)
'''
lst = [1,5,3,7,8,2]
for i,v in enumerate(lst): #两个值就是元组的解包
    print(i,v)
'''
0 1
1 5
2 3
3 7
4 8
5 2
'''

 

⑨input() 控制台输入函数

⑩ bool() 布尔类型转化

11.eval() 执行一个字符串表达式,并返回表达式的值。---若果有字符串里面有数据运算,可以使用eval()

a = '1 + 2'
print(a)
print(eval(a))
'''
1 + 2
3
'''

12.open() 打开文件  与close()函数对应使用