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的另一个应用是列表和字典生成式.

  • 相关阅读:
    数据结构-树与二叉树-思维导图
    The last packet successfully received from the server was 2,272 milliseconds ago. The last packet sent successfully to the server was 2,258 milliseconds ago.
    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property
    redis学习笔记
    AJAX校验注册用户名是否存在
    AJAX学习笔记
    JSON学习笔记
    JQuery基础知识学习笔记
    Filter、Listener学习笔记
    三层架构学习笔记
  • 原文地址:https://www.cnblogs.com/Finley/p/6374608.html
Copyright © 2011-2022 走看看