python语言基础三

八、 函数

    随着程序越来越复杂, 前面介绍的简单的语句等已经不够用了, 我们想要把一些语句组合起来形成新的东西(就像许多积木堆起来的房子)
    此时产生了这三个东西:  【函数】、 【对象】 、 【模块】

    1. 传参:

def my_first_function(name, age):
    print('my name is {name}, {age} years old.'.format(name=name, age=age))

my_first_function('xiaoming', 20)                    my name is xiaoming, 20 years old.

my_first_function(20, 'xiaoming')                    my name is 20, xiaoming years old.

my_first_function(age=20, name='xiaoming')            my name is xiaoming, 20 years old.

my_first_function('xiaoming')                        TypeError: my_first_function() missing 1 required positional argument: 'age'


如上面, 我的函数接收两个参数 name 和 age , 我在传参数的时候,如果没有指定参数的名字, 则按参数对应的下标给函数里面的参数赋值。
如果指定了参数名字, 则按名字赋值。如果传的参数跟函数接收的参数不匹配,则会抛异常。


如果我不知道自己要传多少个参数, 可以在接收参数的时候使用 * 号, 如下

*变量名         将非关键字参数打包成一个元组

def my_first_function(name, *args):
    print('my name is {name}.'.format(name=name))
    print(args)

my_first_function('xiaom', 'shuo', 'hehe')                            my name is xiaom.            ('shuo', 'hehe')

my_first_function('xiaom', 'shuo', 'hehe', 'nama', 'zhenkeng')        my name is xiaom.            ('shuo', 'hehe', 'nama', 'zhenkeng')


**变量名        将关键字参数打包成一个字典

def my_first_function(name, *args, **kwargs):
    print('my name is {name}.'.format(name=name))
    print(args)
    print(kwargs)


my_first_function('xiaoming', 'hehe', 'zhenkeng', age=15, sex='man')    my name is xiaoming.        ('hehe', 'zhenkeng')        {'age': 15, 'sex': 'man'}


注意 : 当 非关键字参数、* 变量名、 关键字参数、  **变量名 同时出现时, 他们出现的顺序一定要是从左到右,否则会报错!!

def my_first_function(name, *args, father,  **kwargs):
    print('my name is {name}. father is {father} .'.format(name=name, father=father))
    print(args)
    print(kwargs)

my_first_function('xiaoming', 'zhenkeng', father='hehe',  age=15, sex='man')
输出 :
my name is xiaoming. father is hehe .
('zhenkeng',)
{'age': 15, 'sex': 'man'}


def my_first_function(name, father, *args, **kwargs):
    print('my name is {name}. father is {father} .'.format(name=name, father=father))
    print(args)
    print(kwargs)

my_first_function('xiaoming', 'zhenkeng', father='hehe',  age=15, sex='man')
报错 : TypeError: my_first_function() got multiple values for argument 'father'

my_first_function('xiaoming',  father='hehe',  age=15, sex='man')
输出 :             【这样 * 变量名 就为空了】
my name is xiaoming. father is hehe .
()
{'age': 15, 'sex': 'man'}

【形参(parameter)】和【实参(argument)】 :             【跟 C 里面不是一个概念】

def my_first_function(name):
    """
    函数定义过程中的 name 是叫形参,因为他只是一个形式,表示占据一个参数位置
    """
    print('my name is {name}.'.format(name=name))

# 传递给函数的 'xiaoming' 叫做实参, 因为他是具体的参数值!!
my_first_function('xiaom')    


    2. 函数文档:
    我定义一个函数, 为了方便别人和自己以后还能知道这个函数是干嘛的, 我就想要给函数写注释, 这就是所谓的函数文档!!
    可以通过 【 help(函数名) 】 和 【 函数名.__doc__ 】 这两种方式来查看函数文档

# 用来测试函数参数的函数
def my_first_function(name):
    """
    用来测试函数参数的函数
    :param name:
    :param father:
    :param args:
    :param kwargs:
    :return:
    """
    # 打印
    print('my name is {name}. '.format(name=name))

print(help(my_first_function))
输出 :
my_first_function(name)
    用来测试函数参数的函数
    :param name:
    :param father:
    :param args:
    :param kwargs:
    :return:

None

如上, 只有在函数下方的 """ 内容 """ 三引号 里面的内容才能被识别为函数文档 。 

print(my_first_function.__doc__)
输出 :
    用来测试函数参数的函数
    :param name:
    :param father:
    :param args:
    :param kwargs:
    :return:


print(print.__doc__)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.

print(help(print))
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

None

【 help 函数会将 \n 等转义】


    3. 返回值

        python 的函数可以返回多个值(放在列表或者元组里面)

def my_first_function():
    return [1, 2, 3]
print(my_first_function())                [1, 2, 3]

def my_first_function():
    return 1, 2, 3
print(my_first_function())                (1, 2, 3)

    如上, 更加证明了 元组的标志性符号是 , 逗号


    4.作用域        【局部变量】 和 【全局变量】
        【函数】 与 【过程】
        有返回值的叫函数, 没有返回值的叫过程。 python 严格来说只有函数没有过程。
如下 :
# 这个函数有定义 return , 所以打印 xiaoming
def my_second_function(name):
    return name
print(my_second_function('xiaoming'))        xiaoming

# 这个函数虽然没有定义 retuen , 但是也打印了 None, 也是有返回值的(默认返回值)
def my_first_function(name):
    print('my name is {name}. '.format(name=name))
print(my_first_function('xiaoming'))        None

        所以说, python 的所有函数都是会返回某些东西的。


        【局部变量】 和 【全局变量】

def my_first_function():
    name = 'xiaom'
    print(name)                        xiaom
    print(age)                        3
    return [1, 2, 3]

age = 3
print(age)                            3
my_first_function()            
print(name)                            NameError: name 'name' is not defined

如上, 参数 age 在函数外面定义的, 在函数里面和函数外面都可以被 访问, age 是全局变量。
       参数 name 在函数里面定义的, 在函数里面可以访问, 在外面访问就抛异常, name 是局部变量

     为什么会这样呢?
     python 的函数在内存中储存时, 是存储在 【栈】 里面, 在函数开始执行前, 会把变量等资源一个个存到栈里面,
     在执行的过程中, 在栈里面由上到下去找这些资源(变量),使用找到的第一个资源(所以先定义的变量会被后定义的同名变量”覆盖“)。
     在函数执行完之后, 这个 栈 的【空间就会被回收】, 所以在函数里面定义的变量也就不存在了!!!!!所以函数外无法访问函数内的变量。


    可以在函数里面定义一个【跟全局变量同名】【的变量】, 此时在函数中会把函数外面的变量屏蔽掉。
age = 3
def my_first_function():
    age = 5
    print(age)                5
    return [1, 2, 3]


print(age)                    3
my_first_function()
print(age)                    3


     【注意】:在函数内部 【可以直接访问全局变量】,但是【不允许直接【修改】全局变量 】

age = 3
def my_first_function():
    print(age)                UnboundLocalError: local variable 'age' referenced before assignment
    age = 5
    print(age)
    return [1, 2, 3]

print(age)                    3
my_first_function()


    如果我要在函数里面修改全局变量, 想要先使用 【 global 】 关键字对全局变量就行声明

age = 3
def my_first_function():
    global age
    print(age)                3
    age = 5
    print(age)                5
    return [1, 2, 3]

print(age)                    3
my_first_function()
print(age)                    5


    5. 内嵌函数
        即: 在一个函数里面定义另外一个函数, 如下

def func1():
    print('正在调用 func1')

    def func2():
        print('正在调用 func2')
    func2()

func1()        
func2()
    输出 : 
正在调用 func1
正在调用 func2
NameError: name 'func2' is not defined
我在 func1 里面定义 并且调用了 func2, 在调用 func1 的时候,按照 func1 里面的流程调用了 func2, 
在外面调用 func2 的时候, 抛出了一个异常 : NameError: name 'func2' is not defined
这是因为 func2是属于func1内部的,类似函数里面定义的变量, 是局部的。 func2 在func1 函数执行完之后就被销毁了。

def func1():
    x = 5
    def func2():
        x *= x                     UnboundLocalError: local variable 'x' referenced before assignment
        return x
    return func2()

print(func1())

def func1():
    x = 5
    def func2():
        return x
    return func2()

print(func1())

如上, func1 里面的变量 x 相当于 func2 里面的外部变量, func2 可以【直接访问这个外部变量】, 但是【不能直接修改这个外部变量】,
    原理与 局部变量跟全局变量的关系一样。

如果我非要修改呢?那我们可以把变量放到 【容器】 里面,比如放到列表里面,因为列表不是存在栈里面, 所以就不会导致上面的异常 。
def func1():
    x = [5]
    def func2():
        x[0] *= x[0]
        return x[0]
    return func2()

print(func1())                    25

如果我感觉使用列表还是不方便, 有没有类似 global 这样的东东呢?
有的,他就是 【 nonlocal 】 关键字
def func1():
    x = 5
    def func2():
        nonlocal x
        x *= x
        return x
    return func2()

print(func1())                    25        一切正常


    6. 闭包    
        如果在一个内部函数里, 对外部作用域(但不是全局作用域)的变量进行引用, 那么内部函数就会被认为是 【闭包】。

def func1(x):
    def func2(y):
        return x * y
    return func2
i = func1(5)
print(i)                        <function func1.<locals>.func2 at 0x000001CF91C90F28>
print(i(3))                            15

如上, 调用 func1 时就返回了一个 function(函数对象) , 这个 function 就可以认为是一个闭包
我们可以使用 i()  来调用 在 func1 里面定义的函数 func2.。。。。。。。。
这样就相当于在使用 func1 里面的局部函数 。。。。。。。

也可以使用如下方式调用 func2
print(func1(5)(3))                    15

def func1(x):
    def func2(y):
        return x * y
    return func2(3)
print(func1(5))                        15

如上,  我们可以成 func2 就是一个 【闭包】


----------------------------------------------

九、lambda 表达式 【匿名函数】


普通函数与匿名函数 : 

def ds_func(x):
    return 2 * x + 1
print(ds_func(5))                       11

lambda_func = lambda x: 2 * x + 1
print(lambda_func(5))                   11

lambda_func = lambda x, y: x * y

print(lambda_func(5, 6))                30

    【 lambda 】 表达式只是【返回】一个【没有名字】【的】【函数对象】
    当我们不再使用这个返回的函数对象时, 内存回收机制会 自动的 将这个函数使用的内存清除。
    我们不需要考虑资源的申请和释放。

    python写一些执行脚本时,使用 lambda 就可以省下定义函数的过程,比如说我们只是需要写一个简单的脚本来
    管理服务器时间, 我们 就不需要专门定义一个函数然后再写调用, 使用 lambda 就可以使得代码更加精简。


    对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数起个名字也是比较头疼的问题, 
    使用 lambda 就不需要 考虑命名的问题了。


    简化代码的可读性。由于普通的函数印度经常要跳到开头 def 定义部分, 使用 lambda 函数可以省去这样的步骤。


    两个牛逼的 内置函数 (经常和 lambda 一起使用)
        1.filter()      过滤器
            按照某一规则对可迭代对象里面的每个元素进行筛选。接收两个参数,筛选规则(一般是一个函数)和可迭代对象,
            将可迭代对象的每个元素依次传入 筛选规则 对应的函数对象中, 如果函数对象的返回值为 True, 这保留这个元素。
            函数返回一个 可迭代对象, 可以用 list 来获取里面的数据。

a = [0, 5, -3, 9, -6]

print(filter(lambda x: x > 0, a))                   <filter object at 0x0000015ACBE8F8D0>

print(list(filter(lambda x: x > 0, a)))             [5, 9]

print(list(filter(None, a)))                        [5, -3, 9, -6]     (0 被剔除了 )


        2. map()        映射函数
            按照某一规则对可迭代对象里面的每个元素进行映射。接收两个参数,映射规则(一般是一个函数)和可迭代对象,
            将可迭代对象的每个元素依次传入 映射规则 对应的函数对象中, 然后把原来的元素替换成映射规则的返回值。
            函数返回一个 可迭代对象, 可以用 list 来获取里面的数据。

a = [0, 5, -3, 9, -6]

print(map(lambda x: x ** 2, a))                 <map object at 0x0000029E6919F8D0>
    
print(list(map(lambda x: x ** 2, a)))           [0, 25, 9, 81, 36]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值