学Python 函数从青铜到王者

简介: 学Python 函数从青铜到王者

Python 入门第三天



image.png


hello ,欢迎看到黄昏的 python 函数部分,这里主要从介绍函数从入门到超神,如果你在学习的过程中,有问题欢迎咨询我哦,我们一起讨论。

此次文章主要介绍函数的入门级和函数的高级,从定义到装饰器。


Python 函数入门


函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。


函数能提高应用的模块性,和代码的重复利用率


函数有具体的组成部分:函数名,函数体,参数,返回值


从分类上看,函数可分为内置函数 和 自定义函数


为了实现不同的编程需求,还可为函数加上各种规则及作用域的限制,以完成整个功能


1.函数定义


  • 定义函数使用关键字def,后接函数名,再后接放在()中的可选参数列表,最后是冒号。格式如下


def 函数名(参数1,参数2,...,参数N):


  • 例如:


def max(a, b):                           #定义函数名 max 
    if a >= b:
        return a  # 返回a
    else:
        return b  # 返回b
return 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。        


2.函数调用


  • 函数调用


调用时,直接使用函数名称即可
hello("I love Python!")        # 调用函数,结果输出:I love Python!


3.函数的命名规则


  • 函数名的命名有其对应的规则


必须以字母或下划线开头


可以包含任意字母、数字或下划线的组合


不能使用任何特殊字符或标点符号


区分大小写


不能是保留字


不能以数字开头


4.函数的参数


形参是从函数的角度来说的,在定义函数时写到括号中的参数就是形参。所谓形参就是形式上的参数


实参是从调用的角度来说的,在调用函数时写到括号里传给函数的参数就是实参,实参可以是常量、变量、表达式、函数。


实参的个数与类型应与形参一一对应,不能多也不能少


  • 形参与实参的区别:

形参是虚拟的,不占用内存空间。形参变量只有在被调用时才分配内存单元

实参是一个变量,会占用内存空间,数据传送单向,由实参传给形参,不能由形参传给实参

  • 函数的参数有几种:


必备参数:以正确的顺序传入函数。调用时的数量必须和声明时的一样


def get_info(name, age):
    print("My name is %s, I'm %d years old." %(name, age))
get_info('tom',25)
get_info('jerry',16)


关键字参数:关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值


def get_info(name, age):
    print("My name is %s, I'm %d years old." %(name, age))
# get_info(16, 'jerry')      # TypeError: %d format: a number is required, not str
get_info(age=16, name='jerry')  # My name is jerry, I'm 16 years old.


默认参数:调用函数时,默认参数的值如果没有传入,则被认为是默认值


def get_info(name, age, sex='male'):
    print('Name: %s' %name)
    print('age: %d' %age)
    print('Sex: %s' %sex)
get_info('tom',23)
get_info('jerry',30,'female


不定长参数:你可能需要一个函数能处理比当初声明时更多的参数


# def add(x, y):
#     return x + y
def add(*tuples):
    sum=0
    for v in tuples:
        sum += v
    return sum
print(add(1,4,6,9))         # 20
print(add(1,4,6,9,5)) 


  • 参数的位置优先级


关键字参数


默认参数


args不定长参数


kwargs不定长参数


5. 函数的作用域


  • Python中的作用域分4种情况:


L:local,局部作用域,即函数中定义的变量;


E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;


G:globa,全局变量,就是模块级别定义的变量;


B:built-in,系统固定模块里面的变量。


  • 搜索变量的优先级顺序依次是:


作用域局部 > 外层作用域 > 当前模块中的全局 > python内置作用域,也就是LEGB。


x = int(2.9)  # int built-in
g_count = 0  # global
def outer():
    o_count = 1  # enclosing
    def inner():
        i_count = 2  # local
        print(o_count)
    # print(i_count) # 找不到
    inner() 
outer()
# print(o_count) # 找不到
当然,local和enclosing是相对的,enclosing变量相对上层来说也是local


  • 作用域的产生


在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域的,如下代码


if 2 > 1:
    x = 1
print(x)  # 1


这个是没有问题的,if并没有引入一个新的作用域,x仍处在当前作用域中,后面代码可以使用


def test():
    x = 2
print(x)    # NameError: name 'x2' is not defined


def、class、lambda是可以引入新作用域的


  • ***变量的修***改


x = 6
def f2():
    print(x)
    x = 5
f2()
# 错误的原因在于print(x)时,解释器会在局部作用域找,
# 会找到x = 5(函数已经加载到内存),但 x 使用在声明前了,所以报错:
# local variable 'x' referenced before assignment.
# 如何证明找到了x=5呢?简单:注释掉 x=5,x=6
# 报错为:name 'x' is not defined
# 同理
x = 6
def f2():
    x+=1    # local variable 'x' referenced before assignment.
f2()


  • global关键字


当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了,当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下,代码如下\


count = 10
def outer():
    global count
    print(count) 
    count = 100
    print(count)
outer()


  • nonlocal关键字


global 关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量怎么办呢,这时就需要nonlocal关键字了


def outer():
    count = 10
    def inner():
        nonlocal count
        count = 20
        print(count)
    inner()
    print(count)
outer()


  • 总结


变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域;
只有模块、类、及函数才能引入新作用域;
对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;
内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。


Python 高级函数



1.嵌套函数


  • 嵌套


def bar():
    print('in the bar')
def foo(func):
    print('in the foo')
    def inner():
        return func()
    return inner
foo(bar)
# foo(bar)()


2.装饰器之不带参数的func


  • 被装饰的函数


def decorative(func):
    def wrapper():    # 定义一个包装器
        print("Please say something: ")
        func()        # 调用func,这个func是我们自己定义的
        print("No zuo no die...")
    return wrapper
@decorative    # 使用@符号调用装饰器
def show():    # 定义func,名字取什么都无所谓,它只是用来传给装饰器中的func参数
    print("I'm from Mars.")
show()


3. 装饰器之带参数的func


  • 被装饰的函数


def decorative(func):
    def wrapper(x):
        print("Please say something...>")
        func(x)
        print("no zuo no die...")
    return wrapper
@decorative
def show(x):
    print(x)
show("hello,mars.")


4.有参数的装饰器


  • 一个参数的装饰器


def foo(func):
    def inner(arg):
        # 验证
        return func(arg)
    return inner
@foo
def bar(arg):
    print('bar')


  • 两个参数的装饰器


def foo(func):
    def inner(arg1,arg2):
        # 验证
        return func(arg1,arg2)
    return inner
@foo
def bar(arg1,arg2):
    print('bar')


  • 三个参数的装饰器


def foo(func):
    def inner(arg1,arg2,arg3):
        # 验证
        return func(arg1,arg2,arg3)
    return inner
@foo
def bar(arg1,arg2,arg3):
    print('bar')


  • 不固定参数的装饰器


def foo(func):
    def inner(*args,**kwargs):
        # 验证
        return func(*args,**kwargs)
    return inner
@foo
def bar(arg1,arg2,arg3):
    print('bar')


  • 一个函数可以被多个装饰器装饰


def foo(func):
    def inner(*args,**kwargs):
        # 验证
        return func(*args,**kwargs)
    return inner
def foo1(func):
    def inner(*args,**kwargs):
        # 验证
        return func(*args,**kwargs)
    return inner
@foo
@foo1
def bar(arg1,arg2,arg3):
    print('bar')


5.装饰器案例


  • 为函数添加致谢时间的装饰器函数


import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        a = func()
        stop_time = time.time()
        print('The func run time is %s'% (stop_time-start_time))
        return a
    return wrapper
@timmer
def foo():
    time.sleep(3)
    print('in the foo')
print(foo())


  • 页面验证装饰器


假定有三个页面,现在要实现其中2个页面验证登录之后才能访问,另一个页面不用验证即可访问
首先定义三个页面函数:
def index():
    print('Welcome to index page')
    return 'from index page'
def home():
    print('Welcome to home page')
    return 'from home page'
def bbs():
    print('Welcome to bbs page')
    return 'from bbs page'
 然后定义装饰器函数:
 import getpass
user = 'sean'
passwd = 'abc123'
def auth(auth_type='local'):
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            if auth_type == 'local':
                username = input('Username: ').strip()
                password = getpass.getpass("Password: ").strip()
                if username == user and password == passwd:
                    print('authentication passed')
                    func(*args,**kwargs)
            elif auth_type == 'ldap':
                print('This is ldap authentication')
                func(*args,**kwargs)
        return wrapper
    return out_wrapper
 接下来将装饰器分别应用于home函数与bbs函数:
 def index():
    print('Welcome to index page')
    return 'from index page'
@auth('local')
def home():
    print('Welcome to home page')
    return 'from home page'
@auth('ldap')
def bbs():
    print('Welcome to bbs page')
    return 'from bbs page'
# 调用函数
index()
home()
bbs()
相关文章
|
2月前
|
Python
【python从入门到精通】-- 第五战:函数大总结
【python从入门到精通】-- 第五战:函数大总结
80 0
|
21天前
|
搜索推荐 Python
利用Python内置函数实现的冒泡排序算法
在上述代码中,`bubble_sort` 函数接受一个列表 `arr` 作为输入。通过两层循环,外层循环控制排序的轮数,内层循环用于比较相邻的元素并进行交换。如果前一个元素大于后一个元素,就将它们交换位置。
124 67
|
14天前
|
Python
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
42 18
|
6天前
|
数据可视化 DataX Python
Seaborn 教程-绘图函数
Seaborn 教程-绘图函数
37 8
|
15天前
|
Python
Python中的函数
Python中的函数
31 8
|
22天前
|
监控 测试技术 数据库
Python中的装饰器:解锁函数增强的魔法####
本文深入探讨了Python语言中一个既强大又灵活的特性——装饰器(Decorator),它以一种优雅的方式实现了函数功能的扩展与增强。不同于传统的代码复用机制,装饰器通过高阶函数的形式,为开发者提供了在不修改原函数源代码的前提下,动态添加新功能的能力。我们将从装饰器的基本概念入手,逐步解析其工作原理,并通过一系列实例展示如何利用装饰器进行日志记录、性能测试、事务处理等常见任务,最终揭示装饰器在提升代码可读性、维护性和功能性方面的独特价值。 ####
|
29天前
|
Python
Python中的`range`函数与负增长
在Python中,`range`函数用于生成整数序列,支持正向和负向增长。本文详细介绍了如何使用`range`生成负增长的整数序列,并提供了多个实际应用示例,如反向遍历列表、生成倒计时和计算递减等差数列的和。通过这些示例,读者可以更好地掌握`range`函数的使用方法。
45 5
|
2月前
|
Python
Python之函数详解
【10月更文挑战第12天】
Python之函数详解
|
2月前
|
存储 数据安全/隐私保护 索引
|
1月前
|
测试技术 数据安全/隐私保护 Python
探索Python中的装饰器:简化和增强你的函数
【10月更文挑战第24天】在Python编程的海洋中,装饰器是那把可以令你的代码更简洁、更强大的魔法棒。它们不仅能够扩展函数的功能,还能保持代码的整洁性。本文将带你深入了解装饰器的概念、实现方式以及如何通过它们来提升你的代码质量。让我们一起揭开装饰器的神秘面纱,学习如何用它们来打造更加优雅和高效的代码。