Python基础 -- 03 基础语法(函数)

一、函数

1、函数的定义

  • 如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数

2、函数的语法及调用

定义语法:

# def 是定义函数的关键词
def 函数名():
    函数体中要执行的代码

调用函数:

# 函数定义完成后,在需要的地方直接通过函数名()即可进行调用
def fun():
    print("hello world!!!")

# 以下代码即为函数的调用
fun()

注意:函数一定要先定义再调用

3、函数的文档说明

文档说明格式:

"""
    函数的文档说明
"""
def 函数名():
    "此处是编写函数文档说明的地方,需要紧贴着函数定义写,不能写在函数执行代码之后,否则文档将会失效"
    print("hello world!!!")

help(函数名)
"""
控制台输出结果:
        Help on function 函数名 in module __main__:

        函数名()
            此处是编写函数文档说明的地方需要紧贴着函数定义写,不能写在函数执行代码之后,否则文档将会失效
"""

4、函数的四种使用形式

"""
    函数的四种使用形式
"""


# 1.没有参数,没有返回值
def printInfo():
    print("用户信息")


printInfo()


# 2.有参数,没有返回值
def printInfo2(name, age):
    print("用户姓名是:%s" % name)


printInfo2("岳飞", None)


# 3.没有参数,有返回值
def printInfo3():
    a = 10
    if a > 5:
        return  # return : 如果return后面没有任何内容,则返回None。如果没有return,则也表示返回None
                #           None同False、0一样可以用在if判断中,表示条件不成立
    return 12


print(printInfo3())  # None
if printInfo3():
    print("111")
else:  # 222
    print("222")


# 4.有参数,有返回值
def calc(x, y):
    if x.isdigit() & y.isdigit():
        return int(x) + int(y)
    else:
        return "输入的数据不正确"

print(calc(input("请输入第一个数字:"),input("请输入第二个数字:")))

5、函数的参数

(1)、位置参数形式

def printInfo2(name, age):
    print("用户姓名是:%s,年龄是%s" % (name, age))


# 1.位置参数形式:即对应的位置上传递对应的参数
printInfo2("岳飞", None)

(2)、关键字参数形式

def printInfo2(name, age):
    print("用户姓名是:%s,年龄是%s" % (name, age))


# 2.如果调用函数是不确定参数的位置,可以使用关键字参数形式,写法如下:
printInfo2(age=18, name="秦桧")
printInfo2("崇祯", age=18)

(3)、默认参数形式

# 3.默认参数:在定义函数时,就给参数设置默认值

def fun(name, age=18):
    print("name=%s,age=%d"%(name,age))

fun("袁世凯")      # name=袁世凯,age=18   如果调用函数时,没有给参数,则使用默认值
fun("蒋介石",20)   # name=蒋介石,age=20   如果给了参数,就会覆盖默认值

注意:默认参数不能使用可变数据类型,例如:字典列表

(4)、可变参数

"""
    可变参数
"""
# 1. *args : 收集所有的位置参数,合并为元组
def function(*args):        # args 就是可变参数
    print(type(args))       # <class 'tuple'>
    print(args)             # ('袁世凯', '徐世昌', '段祺瑞', '曹汝霖')
    for i in args:
        print(i, end="\t")

function()
function("袁世凯")                             # 袁世凯
function("袁世凯","徐世昌","段祺瑞","曹汝霖")   # 袁世凯	徐世昌	段祺瑞	曹汝霖
function("袁世凯",18)                          # 袁世凯	18


# 2. **args : 收集所有的关键字参数,合并为一个字典
def function2(**args):
    print(type(args))               # <class 'dict'>
    print(args)                     # {'name': '袁世凯', 'age': 18, 'gender': '男', 'address': '北京'}
    for key,value in args.items():
        print(key,value,end="\t")

# 调用函数时,实参必须是关键字参数
function2()
function2(name="袁世凯", age=18, gender="男", address="北京")        # name 袁世凯	age 18	gender 男	address 北京

(5)、命名关键字参数

"""
    命名关键字参数:强制控制命名关键字的个数
"""


# * 代表修饰符,即 * 之后的所有参数都必须使用关键字参数进行传值,* 之前的没有要求
def function(name, age, *, gender, address):
    print(name, age, gender, address)


function("康有为", 20, gender="男", address="北京胡同")     # gender和address必须使用关键字参数

(6)、参数的混合使用

"""
   多种参数的混合使用
"""


# 如果参数没有通过关键字参数传值,默认遵循位置参数的顺序
# 如果有 **kwargs,默认放到最后接收
def function(a, b=20, c="hehe", *args, **kwargs):
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwargs)


# 调用函数
function("梁启超", 22, "北京", 100, 200, 300, 400, 500, action="戊戌变法", time="19世纪末")

"""
    打印结果:
            梁启超
            22
            北京
            (100, 200, 300, 400, 500)
            {'action': '戊戌变法', 'time': '19世纪末'}
"""

6、函数的返回值

"""
    函数的返回值
"""


# 1. return 一个值
def calc(num1, num2, num3):
    """

    :param num1: 左运算数
    :param num2:  运算符
    :param num3: 右运算数
    :return: 返回值
    """
    # pass      pass代表程序走到这一行时不执行任何操作
    if num2 == "+":
        return num1 + num3
    elif num2 == "-":
        return num1 - num3
    elif num2 == "*":
        return num1 * num3
    elif num2 == "/":
        return num1 / num3
    else:
        print("输入的运算符有问题")


# 查看函数的帮助文档
help(calc)

# 调用函数
print(calc(10, "+", 30))  # 40


# 2. return 返回多个值
def caclMore(num1, num2):
    return num1 ** 2, num2 ** 3  # 返回多个值时,默认将返回值打包,即打成一个元组返回


print(caclMore(10, 5))  # (100, 125)
value1, value2 = caclMore(10, 6)        # 此操作是拆包

7、局部变量和全局变量

(1)、局部变量

  • 局部变量,就是在函数内部定义的变量
  • 其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的
  • 因为其作用范围只是在自己的函数内部,所以不同的函数可以定义相同名字的局部变量
  • 局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储
  • 当函数调用时,局部变量被创建,当函数调用完成后这个变量就不能够使用了
(2)、全局变量

  • 在函数外边定义的变量叫做全局变量
  • 全局变量能够在所有的函数中进行访问
  • 当函数内出现局部变量和全局变量相同名字时,函数内部中的 变量名 = 数据 此时理解为定义了一个局部变量,而不是修改全局变量的值
  • 如果在函数中出现global 全局变量的名字 那么这个函数中即使出现和全局变量名相同的变量名 = 数据也理解为对全局变量进行修改,而不是定义局部变量
  • 如果在一个函数中需要对多个全局变量进行修改,那么可以使用

(3)、局部变量和全局变量的使用 -- global关键字

# 在此处声明的变量叫做全局变量
num1 = 1000
num2 = 2000
def test01():
    num1 = 100  # 此处定义的变量叫做局部变量
    # 在函数体内修改全部变量,作用范围只能是函数内,出了函数,全局变量值不变
    num1 = 100
    print(num1)     # 100
    # 如果想在函数内修改全局变量,同时想在函数外也保持修改后的值,需要用到global关键字
    # 注意:使用global关键字修改全局变量,必须先在函数体内声明,再使用
    global num2     # 声明要修改的全局变量
    num2 = 2001     # 此时修改完成之后,在函数外全局变量的值也已经修改

test01()
print(num1)         # 1000
print(num2)         # 2001

"""
    总结:什么时候需要加上global关键字
        1.如果只是使用全局变量的值,有没有global关键字都一样
        2.如果要在函数体内修改局部变量的值,就必须使用global关键字,并且需要先声明,再去修改
        3.如果全局变量是可变数据类型(列表、字典)的值,则不管在函数体内需不需要修改全局变量,都不用加gbal关键字
"""

8、命名空间

(1)、命名空间(作用域):为了防止多个变量名冲突,而引入的一种对变量名作用范围分组的机制。

Python里的命名空间:

  • 局部命名空间:函数内的命名空间就是局部的
  • 全局命名空间:模块内的命名空间就是全局的
  • 内置命名空间:内置函数、异常处理等都是内置命名空间
注意:一个Python表达式,可以访问局部命名空间 和 全局命名空间的变量,如果变量重名,则局部命名空间覆盖全局命名空间。

(2)、命名空间的访问:

locals():包含所有局部变量的命名空间,格式是字典类型

globals():包含所有全局变量的命名空间,格式也是字典类型、

(3)、命名空间的查找顺序: LEGB 规则:  "由内而外" (Python2.2 之前不支持函数嵌套,所有只有LGB)

L - Local :局部命名空间
E - Enclosing Function :嵌套函数的命名空间
G - Global : 全局命名空间
B - Built-in : 内置命名空间

(4)、命名空间的生命周期:某个命名空间里的变量的存活时间

  • 局部命名空间:从函数调用时开始、到函数结束后(return、正常执行结束、抛出异常),是该命名空间下的变量存活时间,函数结束后变量被回收(要么引用计数减1)
  • 全局命名空间:从模块加载(代码执行)开始、到程序执行结束后,是全局命名空间的存活时间
  • 内置命名空间:从Python解释器启动开始、到程序执行结束,是内置命名空间的存活时间。

9、引用

(1)、引用

lis1 = [10, 20, 30]
lis2 = lis1


# lis1 和 lis2 操作的是同一个列表对象,id 相同,值相同,同时操作也同步


# lis1 引用 lis2的数据,不管做任何修改,都会影响所有的引用。


lis1.append(10)
# lis2 也会被修改。
(2)、 浅拷贝: list.copy()   dict.copy()

import copy
copy.copy

# 浅拷贝会创建新的列表对象,id 不一样,但是里面子对象不拷贝,还是是同一个

lis1 = [1,2,3,4]

lis3 = lis1.copy()

# copy() 的当时里面的数据是一样,但是之后 lit1 做任何操作都不会影响lis3

# 列表对象相同,但是子对象不同

str = "gesdg"
str.split("")   # 字符串是不可变类型,会生成新字符串
list.append(10) #列表是可变类型,不会生成新字符串
(3)、深拷贝

import copy
lis1 = [1,23,4]
lis4 = copy.deepcopy(lis1)


# 深拷贝会创建一个和 lis1 没有任何关系的列表


# 不仅id不同,连子对象的id也不同了,操作也不会同步。

总结:不管是引用,还是浅拷贝,还是深拷贝,在使用小整数对象池的时候,小整数id还是一样的。

10、匿名函数(lambda表达式)

"""
    lambda表达式:(匿名函数)
        1. lambda表达式是单一的一种表达式语句,没有语句块。
        2. lambda表达式是为了编写简单的函数而设计的,不能编写复杂的函数。def 定义的函数可以处理复杂的逻辑
        3. lambda默认会有返回值,但是不是通过return返回的,而是在 : 号后面的就代表返回值
        4. lambda表达式可以没有参数,也可以有多个参数(支持可变参数、默认参数等)
        5. lambda表达式的 :后面不能写输出语句,但是可以写表达式、if判断等
"""
# 定义一个普通结构的函数
def test01():
    return 100

"""
    以上函数使用lambda表达式改造如下:
        1. 使用 lambda 关键字,表示后面的是一个lambda表达式
        2. : 前面放置的是函数的入参,如果没有参数可以不写,但是要留出空位置。
        3. : 后面放置的是函数的返回值,如果没有可以不写
"""
lambda : 100        # lambda表达式的写法

# 调用lambda表达式,如果只是执行一次,就可以直接吧lambda放到输出体中
print((lambda : 100)())         # 100

# 或者如下方式调用:该方式是如果多次使用lambda表达式,就可以将lambda表达式赋值给对象,然后多次调用对象
f =lambda : 100
print(f())                      # 100


""" 
    带参数带返回值的lambda表达式
"""
# 定义一个普通的带参数带返回值的函数
def test02(a, b):
    return a + b

print(test02(10, 12))

# 创建lambda表达式对象
f = lambda a, b: a + b
print(f(8,3))           # 11

# 直接调用lambda表达式
print((lambda a, b: a * b)(2, 5))       # 10

"""
    多种情况返回值的lambda表达式
"""
# 定义普通函数
def test03(a, b):
    if a < b:
        return a + b
    else:
        return a - b

# 以上函数体的判断方式不够pythonic(python化),可以用如下方式写(类似于java中的三元表达式)
def test04(a, b):
    # 解释:如果 if a < b 成立,则表达式的结果是 a + b,否则表达式的结果是 a - b
    return a + b if a < b else a - b

print(test03(1, 3))         # 4
print(test04(1, 3))         # 4

# 使用lambda表达式改造上述 test04 的函数如下
f = lambda a, b: a + b if a < b else a -b
print(f(5,3))               # 2
print((lambda a, b: a + b if a < b else a -b)(20,15))       # 5


# lambda表达式的默认参数
f = lambda a, b, c=20: a + b +c
print(f(10,20,100))         # 130


# lambda表达式接收可变参数
f = lambda *args: args
print(f(10,20,30,40,50))        # (10, 20, 30, 40, 50)

f = lambda *args, a=10,b=20: list(args)+[a,b]
print(f(1,2,3,4,5,6))           # [1, 2, 3, 4, 5, 6, 10, 20]

# 字典类型的可变参数
f = lambda **kwargs: kwargs
print(f(name="嬴政", age=18, gender="男"))     # {'name': '嬴政', 'age': 18, 'gender': '男'}

f = lambda **kwargs: {value: key for key, value in kwargs.items()}
print(f(name="嬴政", age=18, gender="男"))     # {'嬴政': 'name', 18: 'age', '男': 'gender'}


# lambda表达式作为函数的参数传递
def test00(a, b, f):
    return f(a, b)

print(test00(10, 20, lambda x, y: x + y))       # 30
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值