函数基础

  函数就是把一段代码封装起来,定义成一个函数,当要使用这段代码的时候,调用该函数即可。函数的作用在于减少重复代码,提高代码可读性,易于扩展。

  一、先来看一个最简单的函数。

def first_func():   # 定义函数
    #写逻辑
    print('hello world!')

first_func()    #调用


--------------------------- hello world! #运行结果

 函数定义规则:

  def  函数名():

    #函数逻辑

    pass

函数调用方式:

  函数名()

  二、参数

def say_hi(name):  #定义时的参数叫形参
    print('Hi,', name)

say_hi('Alex')    # 调用时传入的参数叫实参

----------------------
Hi, Alex

  当参数有多个时,根据参数传入的方式分为位置参数、关键字参数、和非固定参数  

  1、位置参数,函数在调用时,实参和形参的位置必须一一对应,下面的例子如果调用时say_hi(20,'Alex'),则输出:20 is Alex years old.

def say(name, age):
    print('%s is %s years old.' % (name, age))

say('Alex', 20)

----------------------
Alex is 20 years old.

  在定义函数时,可以给形参设置默认值,函数调用时如果不传该参数,则使用默认值,否则使用实传入的值。

  有默认值的形参放到后边。

def say(name, age=20):
    print('%s is %s years old.' % (name, age))

def say2(name, age=20):
    print('%s is %s years old.' % (name, age))

say('Alex')   -->Alex is 20 years old.
say2('Alex', 30)   -->Alex is 30 years old.

  2、关键字参数,在函数调用时指定哪个形参的值是什么

def say(name, age=20):
    print('%s is %s years old.' % (name, age))


say(age=30, name='Alex')  -->Alex is 30 years old.

  当关键字参数和位置参数混合使用时,调用时位置参数在前,关键字参数在后。

  3、非固定参数--*args和**kwargs

  定义函数时使用*args和**kwargs,则在调用时可以传入任意数量的参数。

def say(*args, **kwargs):
    print('args: ', args)
    print('kwargs: ', kwargs)
    for item in args:
        print('Hi,', item)
    for j in kwargs:
        print('%s is eating.' % kwargs[j])

say('Alex', 'Rice', 'Black', p1='cat', p2='dag')

-----------------------------------------------
args:  ('Alex', 'Rice', 'Black')
kwargs:  {'p1': 'cat', 'p2': 'dag'}
Hi, Alex
Hi, Rice
Hi, Black
cat is eating.
dag is eating.

  可以看到,位置参数以元组形式传给了args,关键字参数以字典形式传给了kwargs(不能写成say_hi('Alex', 'Rice', p1='cat', p2='dag', 'Black'))

  

  如果在调用的时候人为的传入列表、字典、或元组呢?

say_hi(*['Alex', 'Rice', 'Black'], **{'p1': 'cat', 'p2': 'dag'})

  输出结果与上面是相同的。

   

def func(*args,  name=1, **kwargs,):
    print(args)
    print(name)
    print(kwargs)
    return 1


a = func(11, 22, 33, x=123, y=456, )
b = func(11, 22, 33, name=123, x=123, y=456, )
c = func(11, 22, 33, x=123, y=456, name=123, )
########################
(11, 22, 33)
1
{'x': 123, 'y': 456}
(11, 22, 33)
123
{'x': 123, 'y': 456}
(11, 22, 33)
123
{'x': 123, 'y': 456}
这样玩儿也行?

 参数顺序:位置参数,args,默认值参数, kwargs

def f1(x, y, *args, z='2', **kwargs, ):
    print(z)
    print(args)
    print(kwargs)

# 默认值参数位置
f1(1, 2, 'a', 'b', 5, 4, z='zz', q=3, w=123, e='456')
f1(1, 2, 'a', 'b', 5, 4, q=3, z='zz', w=123, e='456')

  三、返回值

  函数的返回值用return,前面没写,默认返回None

def calc(a, b):
    result = a+b
    return 'result', result
    print('哈哈哈')

ret = calc(1, 2)
print(ret)
-------------------
('result', 3)

  可以看出,打印函数的执行结果得到函数的返回值,返回值可以有多个,并且当遇到return时,函数结束。在程序中可以根据函数的返回值做一些相应的操作。

  

  四、局部变量

  尝试一下在函数内部修改变量

name = 'alex'  
# print(id(name)) 
def change_name():
    # global name   # 强改全局变量
    name = '土豪'
    print('-->', name) 
    # print(id(name))

change_name()
print(name)

-------------------------
--> 土豪 
alex 

  what?为什么没有改成功呢,看一下ID吧,可以看到函数内部和外部的name其实是两个不同的变量,如果硬要改,就使用global关键字,声明name是全局变量,但是,不要随便这么用。

  五、作用域

  在python中,一个函数就是一个作用域。

  

name = "lzl"
def f1():
    name = "Eric"
    def f2():
        name = "Snor"
        print(name)
    f2()
f1()
作用域链
name = "lzl"


def f1():
    print(name)


def f2():
    name = "eric"
    f1()

f2()
终极版作用域
name = "lzl"
 
def f1():
    print(name)
 
def f2():
    name = "eric"
    return f1
 
ret = f2()
ret()

>>:'lzl'
分析

  在函数未执行之前,作用域已经形成了,作用域链也生成了

原文地址:https://www.cnblogs.com/webc/p/8920166.html