zoukankan      html  css  js  c++  java
  • Python函数

    Python使用def关键字定义函数:

    def area(width, height):
    	return width * height
    

    Python提供了返回多个值的语法,实际上是将它们作为一个元组返回:

    def multi_return():
      return 1,2
    
    >>>multi_return()
    (1,2)
    

    参数和返回值传递采用浅拷贝方式,即只拷贝对象本身,其成员指向的其它对象不进行拷贝.

    对象本身被拷贝,函数无法影响实参 :

    >>> def swap(a,b):
    ...   b,a=a,b
    ...
    >>> a = 1
    >>> b = 2
    >>> swap(1,2)
    >>> a
    1
    >>> b
    2
    

    对象引用的其它对象没有拷贝, 函数可以影响实参的元素:

    >>> def fun(a):
    ...   a[0] = 2
    ...
    >>> a = [1]
    >>> fun(a)
    >>> a
    [2]
    

    Python提供了lambda关键字定义匿名函数:

    >>> lam = lambda x,y: x + y
    >>> print(lam(1,2))
    3
    

    Python的函数也是对象, 因此可以方便的进行回调:

    def func(callback, args):
    	callback(args)
    

    函数也是对象的特性, 为许多函数功能提供了支持.

    Python允许函数嵌套定义,并采用链式作用域,内部函数可以访问外部函数的作用域.

    因为Python中可以不声明直接使用对象, 在内部函数访问外部作用域时建议使用global关键字声明.

    Python不检查参数的类型,建议必要时使用isinstance进行检查.

    locals()方法返回保存函数当前作用域内所有变量的字典:

    >>> def func():
    ...   a = 1
    ...   b = 2
    ...   return locals()
    ...
    >>> func()
    {'a': 1, 'b': 2}
    

    因为采用浅拷贝的方式传递,我们可以进行一些修改:

    >>> def func():
    ...   a = [1]
    ...   locals()['a'][0] = 233
    ...   return a
    ...
    >>> func()
    [233]
    

    参数

    Python函数除了上文提到的参数形式(称作位置参数)外, 还提供了更多参数机制:

    默认参数:

    >>> def volume(radius=1, height=1):
     	...	  return math.pi * (radius ** 2)* height
    
    >>> volume(2)
    12.566370614359172
    

    在有默认参数的情况下可以指定只对特殊的默认参数赋值:

    >>> volume(height=2)
    6.283185307179586
    

    可变参数用*修饰,所有可变参数作为一个元组传入:

    >>> def func(*args):
    ...   print(args)
    >>> func(1,2)
    (1, 2)
    

    关键字参数用**修饰, 所有关键字参数作为一个字典传入:

    >>>def func(**kwargs):
        print(kwargs)
    
    >>> func(key='val')
    {'key': 'val'}
    
    >>> func(**{'key':'val'})
    {'key': 'val'}
    

    默认参数可以用命名关键字的方式传入:

    >>> def volume(radius=1, height=1):
    ...	  return math.pi * (radius ** 2)* height
     	
    >>> volume(height=2)
    6.283185307179586
    

    Python3开始支持命名关键字参数,只允许给定的关键字:

    >>>def func(*, kwarg):
    	print(kwarg)
    
    >>>func(kwarg='val')
    'val'
    

    命名关键字参数中*仅作为作为分隔符.

    为了避免二义性,5种参数的顺序为:位置参数, 默认参数, 可变参数/命名关键字参数,关键字参数

    decorator

    装饰器可以方便的为函数动态添加功能:

    import time
    
    def decorator(func):
      def wrapper(arg):
      	print('logging',time.localtime())
      	return func(arg)
      return wrapper
    
    @decorator
    def func(arg):
      print(arg)
    
    >>> func('hello')
    logging time.struct_time(tm_year=2016, tm_mon=2,...
    'hello'
    

    从上述示例中>>> func(arg)实际上调用了decorator(func)(arg).

    装饰器是一个函数, 无参数的装饰器decorator接受被修饰的函数func做参数,返回函数wrapper.

    调用func的实参被传给wrapper, 即wrapper函数代替func被调用.

    为了防止wrapper和func的环境变量不同导致调用出错, 建议使用functools.wraps装饰器保证正确:

    import time
    from functools import wraps
    
    def decorator(func):
        @wraps(func)
        def wrapper(arg):
            print('logging',time.localtime())
            return func(arg)
        return wrapper
    
    @decorator
    def func(arg):
        print(arg)
    
    func('hello')
    

    含有参数的装饰器需要再加一层嵌套:

    import time
    
    def log(text):
    	def decorator(func):
    		def wrapper(arg):
    			print(text)
    			return func(arg)
    		return wrapper
    	return decorator
    
    @log('invoke')
    def func(arg):
    	print(arg)
    

    调用>>>func(arg)等价于>>>log('invoke')(func)(arg)

    generator

    生成器是一类特殊的函数对象, 它使用yield关键字代替return.

    当调用其next()方法或使用for-in遍历generator时, 每次执行到yield语句就记录断点并返回.

    下次调用next()或下次迭代时, 从断点处继续执行.

    虽然generator的语法类似函数,但是:

    >>> obj = fibo
    >>> obj
    <function fibo at 0x0000000002F19F98>
    >>> obj = fibo(max)
    >>> obj
    <generator object fibo at 0x0000000002F32438>
    

    send(msg)是generator另外一个重要方法,在后面协程部分有如下代码:

    def consumer():
    r = ''
    while True:
        n1 = yield r
        if not n1:
            return
        print('Consuming %s' % n1)
        r = 'OK'
    
    def produce(c):
        c.send(None)
        n = 0
        while n < 5:
            n = n + 1
            print('Producing %s' % n)
            r = c.send(n)
            print('Consumer return: %s' % r)
        c.close()
    
    c = consumer()
    produce(c)
    

    第一次启动generator只能使用next()或send(None).

    在consumer()第一次遇yield返回时n1没有被定义.

    produce()函数调用c.send(n)把实参值赋给yield的左值n1并从下一行开始继续执行consumer.

    generator的另一个应用是列表和字典生成式.

  • 相关阅读:
    muduo网络库TcpConnection对象生存期管理
    马:ma一个与代码无关的隐形眼镜的度数换算
    分享ORACLE数据库密码口令过期被锁后的解锁方法
    关于SVN状态图标不显示的解决办法(史上最全)
    Windows 新增远程桌面会话连接数(可多人同时远程桌面,互不影响)
    js移除字符串的中文/空格
    ORA-00059: 超出 DB_FILES 的最大值
    ORA-02292违反完整约束和ORA-02297无法禁用约束条件 cascade禁用主键
    SVN—org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir
    js金额格式化
  • 原文地址:https://www.cnblogs.com/Finley/p/6374608.html
Copyright © 2011-2022 走看看