zoukankan      html  css  js  c++  java
  • 4. 函数参数

    1、默认参数

    def power(x, n = 2):
        s = 1
        while n > 0:
            n = n - 1
            s = s * x
        return s
    

    调用

    >>> power(5)
    25
    >>> power(5, 2)
    25
    

    设置默认参数的注意点:

    • 必选参数在前,默认参数在后,否则Python会报错
    • 当函数有多个参数时,变化大的参数放在前面,变化小的参数放在后面,变化小的参数可以作为默认参数

    默认参数的坑演示:

    # 先定义一个函数,传入一个list,添加一个END再返回
    def add_end(L = []):
        L.aappend('END')
        return L
    # 正常调用结果似乎不错
    >>> add_end([1, 2, 3])
    [1, 2, 3, 'END']
    >>> add_end(['x', 'y', 'z'])
    ['x', 'y', 'z', 'END']
    # 开始使用默认参数,开始结果正确
    >>> add_end()
    ['END']
    
    # 但再次调用add_end()时
    >>> add_end()
    ['END', 'END']
    >>> add_end()
    ['END', 'END', 'END']
    

    默认参数是[],但函数似乎每次都‘’记住了‘上次添加的’END‘的list。

    原因:Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

    默认参数必须指向不变对象!

    要修改上面的例子,我们可以用None这个不变对象来实现:

    def add_end(L=None):
    	if L is None:
    		L = []
    	L.append('END')
    	return L
    
    # 调用
    >>> add_end()
    ['END']
    >>> add_end()
    ['END']
    

    为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。

    2、可变参数

    def calc(*numbers):
        sum = 0
        for n in numbers:
            sum = sum + n * n
        return sum
    
    >>> calc(1, 2, 3)
    14
    >>> calc(1, 3, 5, 7)
    84
    >>> calc()
    0
    

    定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。

    如果已经有一个list或者tuple,要调用一个可变参数怎么办?

    # 法一
    >>> nums = [1, 2, 3]
    >>> calc(nums[0], nums[1], nums[2])
    14
    
    # 法二
    >>> nums = [1, 2, 3]
    >>> calc(*nums)
    14
    

    Python允许在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去。

    3、关键字参数

    关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

    def person(name, gao, **kw):
    	print('name:', name, 'age:', age, 'other:', kw)
    
    # 只传入必选参数
    >>> person('Michel', 30)
    name:Michel age:30 other:{}
    # 传入任意个数的关键字参数
    >>> person('Bob', 35, city='Beijing')
    name: Bob age: 35 other: {'city': 'Beijing'}
    >>> person('Adam', 45, gender='M', job='Engineer')
    name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
    

    和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去

    >>> extra = {'city': 'Beijing', 'job': 'Engineer'}
    >>> person('Jack', 24, **extra)
    name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
    

    **extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。

    4、命名关键字参数

    对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。如果要限制关键字参数的名字,就可以用命名关键字参数

    例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

    def person(name, age, *, city, job):
        print(name, age, city, job)
    

    和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数

    >>> person('Jack', 24, city='Beijing', job='Engineer')
    Jack 24 Beijing Engineer
    

    命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错;原因:调用命名参数缺少参数名时,Python解释器把函数参数均视为位置参数。

    # 命名关键字参数可以有缺省值,从而简化调用:
    def person(name, age, *, city='Beijing', job):
    	print(name, age, city, job)
    

    5、组合参数

    在Python中定义函数,可以用必选参数默认参数可变参数关键字参数命名关键字参数,这5种参数都可以组合使用。

    参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关键字参数。

    def f1(a, b, c=0, *args, **kw):
    	print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    
    >>> args = (1, 2, 3, 4)
    >>> kw = {'d': 99, 'x': '#'}
    >>> f1(*args, **kw)
    a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}    
    
    def f2(a, b, c=0, *, d, **kw):
    	print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
        
    >>> args = (1, 2, 3)
    >>> kw = {'d': 88, 'x': '#'}
    >>> f2(*args, **kw)
    a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
    

    对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

  • 相关阅读:
    javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码
    windows查看端口占用 windows端口占用 查找端口占用程序 强制结束端口占用 查看某个端口被占用的解决方法 如何查看Windows下端口占用情况
    javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url
    ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段
    HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码
    Servlet主要相关类核心类 容器调用的过程浅析 servlet解读 怎么调用 Servlet是什么 工作机制
    linq查询语句转mongodb
    winddows rabbitmq安装与配置
    Redis For Windows安装及密码
    出现,视图必须派生自 WebViewPage 或 WebViewPage错误解决方法
  • 原文地址:https://www.cnblogs.com/BigMario/p/13577471.html
Copyright © 2011-2022 走看看