Python学习第四天之函数

柳三千

前言

   在 Python 中,函数是将一段实现功能的完整代码,使用函数名称进行封装,通过函数名称进行调用。以此达到一次编写,多次调用的目的。它可以接受输入参数,并返回一个或多个值。

一、函数基础

1. **定义函数**

#自定义函数
def 函数名称 (参数列表):
    函数体
    [return 返回值列表]


2. **函数调用**

def get_sum(num):
    s=0
    for i in range(1,num+1):
        s+=i
    print (f'1到{num}之间的累加和为:{s}')


#函数的调用
a=get_sum(8)
# 1到8之间的累加和为:36

a=get_sum(100)
# 1到100之间的累加和为:5050

a=get_sum(1000)
# 1到1000之间的累加和为:500500


3. **参数传递**
- 传递的是对象的引用
- 不可变对象(数字、字符串、元组)传值
- 可变对象(列表、字典)传引用
图片.png


二、参数类型

图片.png


1. **位置参数**

def happy_birthday(name,age):
    print('祝'+ name +'生日快乐!')
    print(str(age)+'岁生日快乐!')

#调用
a=happy_birthday('小美',18)

# 祝小美生日快乐!
# 18岁生日快乐!

--------------------------------------------------------------------
#报错演示
a=happy_birthday('小美')
# Traceback (most recent call last):
#   File "f:\Code\Python\test.py", line 12, in <module>
#     a=happy_birthday('小美')
# TypeError: happy_birthday() missing 1 required positional argument: 'age'

a=happy_birthday(18,'小美')
# Traceback (most recent call last):
#   File "f:\Code\Python\test.py", line 18, in <module>
#     a=happy_birthday(18,'小美')
#   File "f:\Code\Python\test.py", line 2, in happy_birthday
#     print('祝'+ name +'生日快乐!')
# TypeError: can only concatenate str (not "int") to str


2. **关键字参数**

def happy_birthday(name,age):
    print('祝'+ name +'生日快乐!')
    print(str(age)+'岁生日快乐!')


#调用,关键字传参
a=happy_birthday(age=21,name='小美')

# 祝小美生日快乐!
# 21岁生日快乐!

#位置参数+关键字参数,位置参数必须在前面
a=happy_birthday('小红',age=25)

# 祝小红生日快乐!
# 25岁生日快乐!

#报错演示
#--------------------------------------------------------------------
a=happy_birthday(age=25'小红')
# PS F:\Code\Python> & D:/python/python.exe f:/Code/Python/test.py
#   File "f:\Code\Python\test.py", line 19
#     a=happy_birthday(age=25,'小红')
#                           ^
# SyntaxError: invalid decimal literal
# PS F:\Code\Python>


3. **默认参数**

def happy_birthday(name='小美',age=18):
    print('祝'+ name +'生日快乐!')
    print(str(age)+'岁生日快乐!')


#调用函数
happy_birthday()

# 祝小美生日快乐!
# 18岁生日快乐!

#调用函数
happy_birthday(age=25,name='小红')
# 祝小红生日快乐!
# 25岁生日快乐!
happy_birthday(age=29)
# 祝小美生日快乐!
# 29岁生日快乐!

happy_birthday(29)
# Traceback (most recent call last):
#   File "f:\Code\Python\test.py", line 18, in <module>
#     happy_birthday(29)
#   File "f:\Code\Python\test.py", line 2, in happy_birthday
#     print('祝'+ name +'生日快乐!')
# TypeError: can only concatenate str (not "int") to str

⚠️ 默认参数应该使用不可变对象

4. **可变参数**

图片.png

- `*args` 接收元组

def fun(*para):
    print(type(para))
    for item in para:
        print (item)


#调用
fun(10,23,36,38,90)
# <class 'tuple'>
# 10
# 23
# 36
# 38

# 90


#传个列表玩玩
fun([1,2,3,4,5,6])
# <class 'tuple'>
# [1, 2, 3, 4, 5, 6]

#对比下差距,这叫做解包操作
fun(*[1,2,3,4,5,6])
# <class 'tuple'>
# 1
# 2
# 3
# 4
# 5
# 6


- `**kwargs` 接收字典

#个数可变的关键字参数
def fun(**kw):
    print(type(kw))
    for k,v in kw.items():
        print(k,'-------',v)

#调用,关键字传参
fun(name='小美',age=18,height=172)
# <class 'dict'>
# name ------- 小美
# age ------- 18
# height ------- 172

d={'name':'小美','age':20,'height':'182'}
fun(**d)            #**解包操作
# <class 'dict'>
# name ------- 小美
# age ------- 20
# height ------- 182

fun(d)        #报错
# Traceback (most recent call last):
#   File "f:\Code\Python\test.py", line 21, in <module>
#     fun(d)
# TypeError: fun() takes 0 positional arguments but 1 was given
# PS F:\Code\Python>


5. **参数组合顺序**

def func(a, b=0, *args, c, d=1, **kwargs):
    pass

正确顺序:位置参数 → 默认参数 → *args → 关键字参数 → **kwargs

三、返回值

图片.png

1. 可返回多个值(实际返回元组)

def calc(a,b):
    s=a+b
    return s

a=calc(10,20)
print(type(a))
print(a)

# <class 'int'>

# 30


get_s2=calc(calc(10,20),30)
print(get_s2)

# 60


#返回多个值
def get_sum(num):
    s=0 #累加和
    odd_sum=0 #奇数和
    even_sum=0 #偶数和
    for i in range(1,num+1):
        if i%2!=0:  #说明是奇数
            odd_sum+=i
        else:
            even_sum+=i
        s+=i
    return odd_sum,even_sum,s
result=get_sum(10)
print(type(result))
print(result)
# <class 'tuple'>
# (25, 30, 55)

#解包赋值
a,b,c=get_sum(10)
print(a)
print(b)
print(c)
# 25
# 30
# 55



2. 函数没有return语句时返回None

def calc(a,b):
    print(a+b)
   
calc(10,20)  
#30


a=calc(10,20)
print (type(a))
print(a)
# 30
# <class 'NoneType'>
# None



四、作用域

图片.png

#局部变量在全局中无法使用
def fun(a,b):
    s = a + b

fun (10,20)
print (a,b,s)
# Traceback (most recent call last):
#   File "f:\Code\Python\test.py", line 6, in <module>
#     print (a,b,s)

# NameError: name 'a' is not defined


#函数内部变量指定成全局变量
def fun(a,b):
    global s  #声明是全局变量
    s = a + b

fun(10,20)
print (s)

#30


#哪个变量优先级高
x=100
def fun(a,b):
    x = 10  #局部变量名称与全局变量名称相同
    s = a + b + x  #局部变量参与运算,局部变量优先级高
    return s
test=fun(10,20)
print(test)





1. **LEGB规则**
   - Local → Enclosed → Global → Built-in

2. **global 关键字**
```python
x = 10
def modify():
    global x
    x = 20
```

3. **nonlocal 关键字**
```python
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
```


五、高级特性

1. **匿名函数 lambda**

图片.png

#常规函数
def calc(a,b):
    return a + b
print(calc(10,20))

#匿名函数
s=lambda a,b:a+b  #s表示的就是匿名函数
print(type(s))
# <class 'function'>

#调用匿名函数
print (s(20,50))
#70

#列表
lst=[10,20,30,40,50]
for i in range(len(lst)):
    print (lst[i])
# 10
# 20
# 30
# 40
# 50

for i in range(len(lst)):
    result=lambda x:x[i] #根据索引值,result是函数类型,x是形式参数
    print(result(lst))#lst是实际参数
# 10
# 20
# 30
# 40
# 50

#根据成绩排名打印
student_scores=[
    {'name':'陈小明','score':98},
    {'name':'王一一','score':86},
    {'name':'天小红','score':100},
    {'name':'白雪儿','score':91}
]
student_scores.sort(key=lambda x:x.get('score'),reverse=True) #降序排列
print(student_scores)

# [{'name': '天小红', 'score': 100}, {'name': '陈小明', 'score': 98}, {'name': '白
# 雪儿', 'score': 91}, {'name': '王一一', 'score': 86}]


2. **递归函数**
图片.png


#递归函数

#阶乘操作
def fac(n):
    if n == 1:
        return 1
    else:
        return n*fac(n-1)
print(fac(5))
#120  5*4*3*2*1

#斐波那契数列 f(n)=f(n-1)+f(n-2)
# 从第三项开始,每项等于前两项之和  1  1  2  3  5  8  13  21  
def fac2(n):
    if n==1 or n==2:
        return 1
    else:
        return fac2(n-1)+fac2(n-2)
print(fac2


3. **闭包**
```python
def make_multiplier(factor):
    def multiply(x):
        return x * factor
    return multiply
times3 = make_multiplier(3)
```

4. **装饰器**
```python
def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"Time used: {time.time()-start}")
        return result
    return wrapper

@timer
def my_function():
    # ...
```

六、其他特性

1. **函数注释**
```python
def add(x: int, y: int) -> int:
    return x + y
```

2. **函数作为参数传递**
```python
def apply(func, data):
    return [func(x) for x in data]
```

3. **参数解包**
```python
args = (3, 4)
kwargs = {'b': 5, 'a': 6}
func(*args)       # 等价于 func(3, 4)
func(**kwargs)    # 等价于 func(a=6, b=5)
```
---

### 注意事项
1. 避免修改可变默认参数
2. 装饰器会改变函数的元信息,可用 `@functools.wraps` 保持原信息
3. 合理控制递归深度(Python默认递归深度不超过1000)

建议通过实际编写不同参数组合的函数来加深理解,可以使用 `help(function_name)` 查看函数的文档字符串,`dir(function_name)` 查看函数属性。

文章版权声明:除非注明,否则均为柳三千运维录原创文章,转载或复制请以超链接形式并注明出处。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码