Python基础知识——6.函数

6. 函数

函数是代码的组织形式,通过使用函数,程序编写、阅读、测试和修复起来都更加容易。

带名字的代码块,目的是重复使用

函数是带名字的代码块,如果需要多次执行相同功能,只需要调用函数即可,无需重复写代码。在 Python 中,函数是一等对象。编程语言理论家把“一等对象”定义为满足下述条件的程序实体:

  1. 在运行时创建
  2. 能赋值给变量或数据结构中的元素
  3. 能作为参数传给函数
  4. 能作为函数的返回结果

函数是 Python 内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。

6.1 定义函数

# 没有运行参数,没有返回值(返回一个None)
def greeting():
    """显示简单的问候 —— 方法中的第一行字符串,可以当做方法的文档"""
    print('hello world')

greeting()	# 调用该方法

在这里插入图片描述

以 # 号开头进行注释则不会显示方法的文档

6.1.1 向函数传递参数

def greeting2(user_name):
    print(f'hello {user_name}')


greeting2('dream')
greeting2(user_name="xunmi")

6.1.2 形参和实参

函数定义中的参数叫形参,函数调用时传递的具体参数的值叫实参

def information(subject):	# 这里的subject为形参
    print(f'我学了{subject}课程')


subjects = ['Python', 'JAVA', 'excel', 'C++']
for subject in subjects:	# 这里的subject为实参
    information(subject)	

我学了Python课程
我学了JAVA课程
我学了excel课程
我学了C++课程

6.2 传递参数

6.2.1 位置参数

调用的时候严格按照参数的位置顺序

def desc_pet(pet_type, pet_name):
    """显示宠物信息,参数:宠物物种,宠物名字"""
    print(f'我有一只{pet_type},它的名字是{pet_name}')


desc_pet('狗', '钢镚')

我有一只狗,它的名字是钢镚

6.2.2 关键字参数

直接使用形参的名字

desc_pet(pet_name = '钢镚', pet_type = '狗')

6.2.3 默认值

默认值放在位置参数的后面

def desc_pet(pet_name, pet_type = 'dog'):
    """显示宠物信息,参数:宠物物种,宠物名字"""
    print(f'我有一只{pet_type},它的名字是{pet_name}')


desc_pet('钢镚')

我有一只dog,它的名字是钢镚

desc_pet('钢镚', pet_type='乌龟')	# 覆盖默认值

6.3 返回值

return,# 如无return 则无法在函数以外运用得到的值,使用返回值时会返回None

6.3.1 返回简单值

def get_full_name(first_name, last_name):
    """返回完整的名字"""
    full_name = first_name + ' ' + last_name
    return full_name	# 如无return <value> 则无法在函数以外运用得到的值,使用返回值时会返回None

full_name = get_full_name('lizz', 'Truss')
print(full_name)

lizz Truss

如无 return full_name 则输出为:None

6.3.2 返回字典

def build_person(first_name, last_name, age=None):
    """返回一个字典,包含某人的信息"""
    person = {
        'first': first_name.title(),
        'last': last_name.title()
    }
    if age:
        person['age'] = age
    return person


someone = build_person('john', 'snow', 28)
print(someone)

{'first': 'John', 'last': 'Snow', 'age': 28}

practice
# 通过输入得到人员姓名,并且输入Q时退出程序  (使用上方<build_person>方法)
while True:
    first_name = input('请告诉我你的First Name:')
    if first_name == 'Q':
        print('结束')
        break
    else:
        last_name = input('请告诉我你的Last Name:')
        if last_name == 'Q':
            print('结束')
            break
        else:
            full_name = build_person(first_name, last_name)
            print(full_name)

代码精简后

while True:
    first_name = input('请告诉我你的First Name:')
    if first_name == 'Q':
        break
    last_name = input('请告诉我你的Last Name:')
    if last_name == 'Q':
        break
    full_name = build_person(first_name, last_name)
    print(full_name)

print('\n退出循环')

6.4 传递任意数量的参数

在形参名字前面加一个 * ,在函数内部,输入的参数放在同一个元组中,名字就是形参的名字

def sum(*args):
    _sum = 0
    for num in args:
        _sum += num

    return _sum


_sum = sum(1, 2, 3, -3)
print(_sum)

6.4.1 可变参数的位置

def make_pizza(*stuffs, size='9寸'):  # 可变参数放在位置参数的后面
    """打印披萨的所有配料"""
    print(f'披萨的尺寸为{size}')
    for stuff in stuffs:
        print(stuff)


make_pizza('蘑菇', '芝士', size='8寸')   # 如果包含了可变参数和默认参数,默认参数要放在后面

6.4.2 可变数量的关键字参数

形参名字前加 ** ,在函数内部当作字典使用

def user_information(**user_profile):
    return user_profile


print(user_information(name = '王大锤', age =20 ))

6.4.3特殊参数

通常情况下参数可以按位置或显式关键字传递给 Python 函数。

为了让代码易读、高效,最好限制参数的传递方式,这样开发者只需查看函数定义,即可确定参数项是 仅按位置、按位置或关键字,还是仅按关键字传递。完整函数定义如下:
在这里插入图片描述

/ 和 * 是可选的。这些符号表明形参如何把参数值传递给函数:位置、位置或关键字、关键字

  1. 函数定义中未使用 / 和 * 时,参数可以按位置或关键字传递给函数。
  2. 仅限位置形参应放在 / (正斜杠)前
  3. 仅限关键字形参应放在 * 后

参数定义的顺序必须是:位置参数、默认参数、可变参数(元组、字典)

def f(a, b, c=0, *args, **kw):

6.5 递归函数

在函数内部可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。

def recur_fibo(n):
    """递归函数输出斐波那契数列<后一个数字为前两个数字之和>"""
    if n <= 2:
        return n
    else:
        return(recur_fibo(n-1) + recur_fibo(n-2))
print(recur_fibo(5))	# 值为8

6.6 高阶函数

6.6.1 高阶函数的概念

函数里的参数可以是函数,返回值也可以是函数,甚至函数还可以赋值给其他变量

z = abs  # 一个变量可以指向函数


def add(x, y, z):   # 第三个变量为一个函数
    return z(x) + z(y)


def foo(x):
    return 10*abs(x)


print(add(-5, 7, foo))      # 通过函数套用的方式执行代码(三层函数套用 —— z,add,foo)

120

6.6.2 匿名函数

在python中,匿名函数,顾名思义就是没有名字的函数,它主要用在那些只使用一次的场景中。这种场景下使用匿名函数往往能够让你的程序更加简单。匿名函数不需要显示地定义函数名,关键字 lambda 表示匿名函数,因此匿名函数也叫lambd函数:

lambda [arg1 [,arg2, ... argN]] : expression

lambda 式子中冒号前面的是函数参数, 冒号后面的是函数的返回值。

注意: lambda 函数必须为单行,且不能包含 return 语句,返回值就是该表达式的结果。

# 常规函数 ,求两个数的和
def adder(x, y):
    return x + y

#改写成匿名函数
lambda x,y:x+y

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象, 也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

# 赋值给变量
adder = lambda x, y: x + y
print(adder(2, 5))

6.6.3 Python内置高阶函数

1. map

map() 函数接收两个参数,一个是函数,一个是可迭代集合, map将传入的函数依次作用到集合的每个 元素,并把结果作为新的可迭代集合返回

numbers = [i**2 for i in list(range(10))]
print(numbers)

def square(x):
    return x**2

print(list(map(square, numbers)))

print(list(map(lambda x: x**2, numbers)))	# 使用匿名函数一行代码即可实现

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561]
[0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561]

2. reduce()

reduce 不是内置函数,使用前需要导入;而map是内置函数,可以直接使用

from functools import reduce  # 导入

与map类似, reduce 函数接收两个参数,一个是函数,一个是可迭代集合。 reduce () 把一个函数作用 在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数, reduce把结果继续和序列的下一个元素做函 数运算,最终输出单一值。完整语法是:

reduce(function, iterable, [initializer])

在这里插入图片描述

# 使用reduce计算1-100的和
from functools import reduce  # 导入

numbers = list(range(1, 101))

def add(x, y):
    return x+y
print(add, numbers)		# 或者定义匿名函数实现

print(reduce(lambda x, y: x+y, numbers))
# reduce方法实现将整数列表变成连在一起的整数(方法1)
from functools import reduce  # 导入

numbers = [1, 3, 4, 1]

def add(x, y):
    return str(x)+str(y)

print(intreduce(add, numbers))
# reduce方法实现将整数列表变成连在一起的整数(方法2:使用不同函数进行处理)
from functools import reduce  # 导入

numbers = [1, 3, 4, 1]

def add(x, y):
    return x*10 + y

print(reduce(add, numbers))

1341

#计算10的阶乘
from functools import reduce  # 导入

def factorial(x, y):    # 方法1
    return x * y

print(reduce(factorial, list(range(1, 11))))


i = 1    # 方法2
q = 1
while i <= 10:
    q = i * q
    i += 1
print(q)


print(reduce(lambda x, y: x * y, list(range(1, 11))))    # 方法3

3628800

3. filter

filter() 函数接收两个参数,一个是函数,一个是可迭代集合。对集合中的每一项依次执行函数,将执行结果为True的元素保留,为False的元素则删除,以此来对集合进行过滤。

# 保留负数
num_list = [1, -1, -2, 0, 2, 3, 6]


def fn(x):
    return x < 0


print(list(filter(fn, num_list)))

6.7 将函数保存到模块

6.7.1 导入模块

创建自己的模块时,要注意:

  1. 模块名要遵循Python变量命名规范,不要使用中文、特殊字符;
  2. 模块名不要和系统模块名冲突,最好先查看系统是否已存在该模块。

下面是一个建议的模块格式:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" 第一个字符串是模块说明。下面是一些文档元素据,作者、版权、修订历史之类 """
__author__ = 'wincheer yang'

# 导入必要的模块
import sys

# 函数
def foo():
pass
def my_func2(name):
    print('你好 % s' % name)

# 入口函数
if __name__ == '__main__':
    print('这里是本模块的入口处。命令行 python 本模块名 .py 将执行这里的代码')

导入模块的方法有多种:

# 导入全部函数
import first_module
first_module.foo() # 调用函数 - 模块名 .函数(参数)

# 导入指定函数
from first_module from first_module from first_module foo() # 调用函数 -   
import foo # 导入指定函数
import foo,bar # 导入多个函数
import * # 导入全部函数
# 函数(参数) ,无需指定模块名

# 给函数指定别名
from first_module import foo as fn
fn() # 调用函数 - 函数别名(参数) ,无需指定模块名

# 给模块指定别名
import first_module as m
m.foo() # 调用函数 - 模块别名 .函数(参数)

6.7.2 包

Python 2.x 的规定,每一个包目录下面都会有一个__init__.py的文件,否则Python就把这个目录当成普通目录而不是一个包。而在 Python 3.x 中,init.py 对包来说并不是必须的。

from com.wlw.pythom.hello import wlw  #from <文件位置> import <模块名称>

项目结构示例:

在这里插入图片描述

  • project/ :项目模块顶层包,通常顶层包下按功能组织模块
  • docs/:存放一些项目文档。
  • setup.py: 安装、部署、打包的脚本。
  • README.md 能简要描述该项目的信息,让读者快速了解这个项目。

6.7.3 模块搜索路径添加

默认情况下, Python解释器会搜索当前项目目录、所有已安装的内置模块和第三方模块。搜索路径存放在 sys模块的path变量中:

import sys
sys.path

如果我们要添加自己的搜索目录,有两种方式:

  1. 直接修改sys.path,添加要搜索的目录:
import sys
sys.path.append(r'D:\wincheer\python-tour') #运行结束后失效
  1. 第二种方法是设置环境变量 PYTHONPATH ,该环境变量的内容会被自动添加到模块搜索路径中。设 置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径, Python自己本身的搜索路径不受影响。
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值