zoukankan      html  css  js  c++  java
  • python 函数基础介绍

    函数是对程序逻辑进行结构化或过程化的一种编程方法。能将整块代码巧妙地隔离成易于管理的小块,把重复代码放在函数中而不是进行大量的拷贝。

    一、函数创建 def

    函数创建格式如下:

    def function_name(arguments):
        "function_documentation_string"
        function_body_suite

    代码实例1-1:

    def say_hello():
        """say hello to somebody"""
        print "hello"

    二、函数调用 ()

    在python中,我们使用一对圆括号来调用函数。如上,运行代码实例1-1,是没有执行函数,没有任何输出的,编译器只是将say_hello变量加载到了内存。

    此时可以运行say_hello(),将调用say_hello函数。正如你可能意识到的,任何输入的参数都必须放置在括号中。如下实例

    代码实例2-1:

    def say_hello(name):
        """say hello to somebody"""
        print "hello %s" % name
    
    say_hello("Milton")
    

    代码实例2-1输出如:

    hello Milton

    三、函数参数(位置参数,默认参数,关键字参数,元组参数,字典参数)

    代码实例3-1:

    def say_hello(_from, _to, times=2):
        """somebody say hello to somebody repeats"""
        print "%s say hello to %s repeat %s times" % (_from, _to, times)
    
    
    say_hello("Milton", "Cherish")
    say_hello(_to="Cherish", _from="Milton", times=10)

    代码实例3-1输出如下:

    Milton say hello to Cherish repeat 2 times
    Milton say hello to Cherish repeat 10 times

    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求就是,关键参数必须放在位置参数之后。

    非固定参数

    若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数

    代码实例3-2:

    def say_hello(_from, _to, *args, **kwargs):
        """somebody say hello to somebody repeats"""
        print "%s say hello to %s " % (_from, _to)
        print "args:", args
        print "kwargs:", kwargs
    
    
    say_hello("Milton", "Cherish", "arg1", "arg2", name="guanfc", age=28)
    print "*" * 100
    say_hello("Milton", "Cherish", ("arg1", "arg2"), name="guanfc", age=28)
    print "*" * 100
    say_hello("Milton", "Cherish", "arg1", "arg2", {"name": "guanfc", "age": 28})
    print "*" * 100
    say_hello("Milton", "Cherish", "arg1", "arg2", **{"name": "guanfc", "age": 28})
    

    实例3-2输出如下:

    Milton say hello to Cherish 
    args: ('arg1', 'arg2')
    kwargs: {'age': 28, 'name': 'guanfc'}
    ****************************************************************************************************
    Milton say hello to Cherish 
    args: (('arg1', 'arg2'),)
    kwargs: {'age': 28, 'name': 'guanfc'}
    ****************************************************************************************************
    Milton say hello to Cherish 
    args: ('arg1', 'arg2', {'age': 28, 'name': 'guanfc'})
    kwargs: {}
    ****************************************************************************************************
    Milton say hello to Cherish 
    args: ('arg1', 'arg2')
    kwargs: {'age': 28, 'name': 'guanfc'}

    def say_hello(_from, _to, *args, **kwargs) 函数定义中,*args代表元组,**kwargs代表键值对。
    当调用如: say_hello("Milton", "Cherish", "arg1", "arg2", name="guanfc", age=28) 时,

      “Milton”对应形参“_from”,
      “Cherish”对应形参“_to”,
      "arg1"和"arg2"对应形参*args,
      name="guanfc",age=28 对应形参**kwargs

    故输出如:

    Milton say hello to Cherish 
    args: ('arg1', 'arg2')
    kwargs: {'age': 28, 'name': 'guanfc'}

    当调用如:say_hello("Milton", "Cherish", "arg1", "arg2", {"name": "guanfc", "age": 28}) 时,

      “Milton”对应形参“_from”,
      “Cherish”对应形参“_to”,
      "arg1","arg2",{"name":"guanfc","age":28} 对应形参*args,
      没有实参对应形参**kwargs

    故输出如:

    Milton say hello to Cherish 
    args: ('arg1', 'arg2', {'age': 28, 'name': 'guanfc'})
    kwargs: {} 

    如果想直接将字典作为实参传入 {"name": "guanfc", "age": 28} 赋值给形参**kwargs,则需要在传入时,在前面添加**,

    如say_hello("Milton", "Cherish", "arg1", "arg2", **{"name": "guanfc", "age": 28})

    故输出如:

    Milton say hello to Cherish 
    args: ('arg1', 'arg2')
    kwargs: {'age': 28, 'name': 'guanfc'}

    如果同时具有元组参数*args和字典参数**kwargs,字典参数**kwargs要放在最后

    四、传递函数

    所有的对象都是通过引用来传递的,函数也不例外。当对一个变量赋值时,实际是将相同对象的引用赋值给这个变量。如果对象是函数的话,这个对象所有的别名都是可调用的。如:

    >>> def say_hello():
    ...   print "say hello~"
    ...
    >>> bar=say_hello
    >>> bar()
    say hello~
    >>>
    

    当我们把say_hello赋值给bar时,bar和say_hello引用了同一个函数对象,所以bar能以和say_hello相同的方式来调用函数,bar()

    我们甚至可以把函数作为参数传入到其他函数来进行调用,如:

    >>> def say_hello():
    ...   print "say hello~"
    ...
    >>>
    >>> def bar(argfunc):
    ...   argfunc()
    ...
    >>> 
    >>> bar(say_hello)
    say hello~
    >>>

    五、匿名函数 lambda

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

    核心笔记:lambda 表达式返回可调用的函数对象

    def add(x,y):return x+y  <==> lambda x,y:x+y

    >>> a=lambda x,y=2:x+y
    >>> a(0)
    2
    >>> a(1)
    3
    >>> a(4,5)
    9
    >>>

    六、内建函数

    filter():给定一个对象的序列和一个“过滤”函数,每个序列元素都通过这个过滤器进行筛选,保留函数返回为真的对象。

    代码实例6-1:

    def select_server(server):
        if server > 5:
            return True
    
    
    server_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print filter(select_server, server_list)
    print filter(lambda server: server > 5, server_list)
    

    代码实例6-1输出如:

    [6, 7, 8, 9]
    [6, 7, 8, 9]

    map():给定一个对象的序列和一个“功能”函数,将函数作用在序列的每个元素上,然后创建由每次函数应用组成的返回值列表。

     代码实例6-2:

    def map_server(server):
        server = int(server) + 10
        return server
    
    
    server_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print map(map_server, server_list)
    print map(lambda server: server + 10, server_list)
    

    代码实例6-2输出如:

    [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

    七、变量作用域(局部变量,全局变量)

    代码实例7-1:

    #!/usr/bin/env python 
    # -*- coding: utf-8 -*-
    
    # 全局变量
    server = 0
    role = "Milton"
    
    
    def map_server():
        global server       # 声明全局变量
        server = 100
        role = "Cherish"    # 局部变量
    
    
    map_server()
    print server  # 输出全局变量,在map_server函数中已被修改-->server==100
    print role    # 输出全局变量--> role == "Milton"
    

    代码实例7-1输出如:

    100
    Milton

    八、闭包

    >>> def counter(start_at=0):
    ...   count=[start_at]
    ...   def incr():
    ...     count[0]+=1
    ...     return count[0]
    ...   return incr
    ...
    >>>
    >>> count=counter(5)
    >>> count()
    6
    >>> count()
    7
    >>> count2=counter(100)
    >>> count2()
    101
    >>> count2()
    102
    >>> count()
    8
    >>>

    九、装饰器(无参,有参,函数)

    装饰器,主要为了实现程序设计的开放封闭原则,在原实现函数不修改的基础上,对原函数功能进行扩展。最终提供的调用方式保持一致。

    封闭:已实现的功能代码块

    开放:对扩展开放

    无参装饰器

    代码实例9-1:

    #!/usr/bin/env python 
    # -*- coding: utf-8 -*-
    
    
    def wrapper(main_func):
        def inner():
            print "I am before login"
            main_func()
            print "I am after login"
    
        return inner
    
    
    @wrapper
    def login():
        print "do login"
    
    
    # 调用方
    login()
    

    代码实例9-1输出如:

    I am before login
    do login
    I am after login
    

    关键代码分析:

    @wrapper
    def login():
      print "do login"
    等同于 当执行login()时
    1.login=wrapper(login)
    2.login()

    代码实例9-1运行过程等同如下:

    #!/usr/bin/env python 
    # -*- coding: utf-8 -*-
    
    
    def wrapper(main_func):
        def inner():
            print "I am before login"
            main_func()
            print "I am after login"
    
        return inner
    
    
    def login():
        print "do login"
    
    
    # 调用方
    login = wrapper(login)
    login()
    

    带参装饰器(被修饰的函数带参,装饰器本身带参)

    代码实例9-2:

    #!/usr/bin/env python 
    # -*- coding: utf-8 -*-
    
    
    def wrapper(main_func):
        def inner(*args, **kwargs):
            print "I am before login"
            main_func(*args, **kwargs)
            print "I am after login"
    
        return inner
    
    
    @wrapper
    def login(name, passwd):
        print "do login,name=%s,passwd=%s" % (name, passwd)
    
    
    # 调用方
    login("Milton", 123456)
    

    代码实例9-3:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    def wrapper(action):
        def outer(main_func):
            def inner(*args, **kwargs):
                print "action == %s" % action
                main_func(*args, **kwargs)
                print "I am after login"
    
            return inner
    
        return outer
    
    
    @wrapper("before login")
    def login(name, passwd):
        print "do login,name=%s,passwd=%s" % (name, passwd)
    
    
    # 调用方
    login("Milton", 123456)
    

    代码实例9-3输出如:

    action == before login
    do login,name=Milton,passwd=123456
    I am after login

    关键代码分析:

    python解释器从上往下扫描到

    @wrapper("before login") 时,执行了

    login=wrapper("before login")(login)

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    def wrapper(action):
        def outer(main_func):
            def inner(*args, **kwargs):
                print "action == %s" % action
                main_func(*args, **kwargs)
                print "I am after login"
    
            return inner
    
        return outer
    
    
    # @wrapper("before login")
    def login(name, passwd):
        print "do login,name=%s,passwd=%s" % (name, passwd)
    
    
    # 调用方
    login=wrapper("before login")(login)
    login("Milton", 123456)

    十、生成器

    什么是Python式的生成器?从语法上讲,生成器是一个带yield语句的函数。一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果--那就是yield语句的功能,返回一个值给调用者并且暂停执行。当生成器的next()方法被调用时,它会准确地从离开地方继续执行。当生成器的send()方法被调用时,yield会接收send方法传入的实参,并且从yield暂停的地方开始继续执行。

    yield输出,代码实例10-1:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    def simple_gen():
        yield 1
        yield '2 -->punch!'
    
    
    # 调用next()方法
    gen = simple_gen()
    print gen.next()
    print "离开去干点别的事"
    print gen.next()
    
    print "*" * 20
    # 使用for循环
    for item in simple_gen():
        print item

    代码实例10-1输出如:

    1
    离开去干点别的事
    2 -->punch!
    ********************
    1
    2 -->punch!

    yield接收输入,代码实例10-2:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    def simple_gen():
        print "waiting for name."
        while True:
            name = yield
            print name
    
    
    gen = simple_gen()  # 创建生成器对象
    gen.next()          # 执行next()方法时,程序运行到name=yield就退出,等待send传入参数。
    gen.send("Milton")  # 一旦调用send()方法,回到yield退出位置,yield接收send实参,并且继续往下运行
    gen.send("Cherish")
    

    实例10-2输出如:

    waiting for name.
    Milton
    Cherish
    

    在交互端如:

    >>> def simple_gen():
    ...   print "waiting for name."
    ...   while True:
    ...     name=yield
    ...     print name
    ...
    >>>
    >>> gen=simple_gen()
    >>> gen.next()
    waiting for name.
    >>> gen.send("Milton")
    Milton
    >>> gen.send("Cherish")
    Cherish
    >>> gen.send("guanfc")
    guanfc
    >>>
    

    通过yield实现在单线程的情况下实现并发运算的效果

    代码实例10-3:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import time
    
    
    def consumer(name):
        print("%s 准备抢红包啦!" % name)
        while True:
            money = yield
            print("红包[%s]来了,被[%s]抢了!" % (money, name))
    
    
    def producer():
        c1 = consumer('A')
        c2 = consumer('B')
        c1.next()
        c2.next()
        print("群主准备发红包啦!")
        for i in range(3):
            time.sleep(1)
            print("群主发了两个红包!")
            c1.send(bytes(i) + "-part1")
            c2.send(bytes(i) + "-part2")
    
    
    producer()
    

    代码实例10-3输出如下:

    A 准备抢红包啦!
    B 准备抢红包啦!
    群主准备发红包啦!
    群主发了两个红包!
    红包[0-part1]来了,被[A]抢了!
    红包[0-part2]来了,被[B]抢了!
    群主发了两个红包!
    红包[1-part1]来了,被[A]抢了!
    红包[1-part2]来了,被[B]抢了!
    群主发了两个红包!
    红包[2-part1]来了,被[A]抢了!
    红包[2-part2]来了,被[B]抢了!
    

      

      


    ***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***
  • 相关阅读:
    基础算法:求目标值 &字符串反转
    算法计算出股票最佳交易时间点
    Python 设计模式—命令模式
    Python 设计模式—代理模式
    有趣的算法题~单调栈
    令人头大的字符串—算法处理
    WebUI 自动化测试的经典设计模式:PO
    双指针—滑动窗口算法解析
    Python 设计模式—观察者模式
    多线程之读写锁原理
  • 原文地址:https://www.cnblogs.com/guanfuchang/p/6044264.html
Copyright © 2011-2022 走看看