一、有用的None:


None是Python中一个特殊的值,虽然它不表示任何数据,但仍然具有重要的作用。虽然None作为布尔值和False是一样的,但是它和False有很多差别。需要把None和不含任何值的空数据结构区分。0值的整型/浮点型、空字符串、空列表、空元组、空字典、空集合都等价于False,但是不等于None。



二、位置参数



>>> def players(mvp,best_scorer,best_reb):



...             return{'mvp':mvp,'best_scorer':best_scorer,'best_reb':best_reb}



...



>>> players('Lebron James','Koby Brant','Ying Mu')



{'best_scorer': 'Koby Brant', 'best_reb': 'Ying Mu', 'mvp': 'Lebron James'}


位置参数的值是按照顺序依次复制过去的,但是位置参数的一个弊端是必须熟记每个位置参数的含义,位置记错了结果就错了。



三、关键字参数


如果同时出现两种参数形式,首先 应该考虑的是位置参数。


>>> players('Lebron James',best_reb = 'Ying Mu',best_scorer = 'Koby Brant')



{'best_scorer': 'Koby Brant', 'best_reb': 'Ying Mu', 'mvp': 'Lebron James'}



四、指定默认参数值


>>> def menu( wine, entree, dessert=' pudding'): 



...             return {'wine': wine, 'entree': entree, 'dessert': dessert}





#默认参数不传递新值时输出默认值,传递新值时输出新值



>>> menu(' chardonnay', 'chicken') 



{'dessert': 'pudding', 'wine': 'chardonnay', 'entree': 'chicken'}





>>> menu(' dunkelfelder', 'duck', 'doughnut') 



{'dessert': 'doughnut', 'wine': 'dunkelfelder', 'entree': 'duck'}


经常犯的一个错误是把可变的数据类型(如列表或者字典)当做默认参数值。



五、使用*收集位置参数


>>> def print_ args(* args): 



...             print(' Positional argument tuple:', args) 



...





#给函数传入的所有参数都会以元组的形式返回输出



>>> print_ args( 3, 2, 1, 'wait!', 'uh...') 



Positional argument tuple: (3, 2, 1, 'wait!', 'uh...')





#如果你的函数同时有限定的位置参数,那么*args会收集剩下的参数



>>> def print_ more( required1, required2, *args): 



...             print(' Need this one:', required1) 



...             print(' Need this one too:', required2) 



...             print(' All the rest:', args) .



.. 



>>> print_ more(' cap', 'gloves', 'scarf', 'monocle', 'mustache wax') 



Need this one: cap 



Need this one too: gloves 



All the rest: ('scarf', 'monocle', 'mustache wax')



六、使用**收集关键字参数


使用两个星号可以将参数收集到一个字典中,参数的名字是字典的键,对应参数的值是字典的值。


>>> def print_ kwargs(** kwargs): 



...             print(' Keyword arguments:', kwargs) 



...





>>> print_ kwargs( wine=' merlot', entree=' mutton', dessert=' macaroon') 



Keyword arguments: {'dessert': 'macaroon', 'wine': 'merlot', 'entree': 'mutton'}


如果把带有*args和**kwargs的位置参数混合起来,它们会按照顺序解析。



七、文档字符串



建议在函数体开始的部分附上函数定义说明的文档


def print_ if_ true( thing, check): 



        ''' 



        Prints the first argument if a second argument is true. 



        The operation is: 



                1. Check whether the *second* argument is true. 



                2. If it is, print the *first* argument. 



        ''' 



        if check: 



                print( thing)



调用Python函数help()可以打印输出一个函数或模块的文档字符串。



八、函数



>>> def answer():



...         print(42)



...



>>> answer()



42






>>> def run_something(func):



...         func()



...



>>> run_something(answer)



42






>>> def add_args(arg1,arg2):



...         print(arg1 + arg2)



...



>>> def run_sth_with_args(func,arg1,arg2):



...         func(arg1,arg2)



...






>>> run_sth_with_args(add_args,5,9)



14






>>> def sum_arg(*args):



...         return sum(args)



...



>>> def run_with_positional_args(func,*args):



...         return func(*args)



...



>>> run_with_positional_args(sum_arg,1,2,3,4)



10



九、内部函数



当需要在函数内部多次执行复杂任务时,内部函数是非常有用的,从而避免了循环和代码的堆叠重复。


>>> def knights( saying): 



...             def inner( quote): .



..                     return "We are the knights who say: '%s'" % quote .



..             return inner( saying) ...



十、闭包


内部函数可以看作一个闭包。闭包是一个可以 由另一个函数动态生成的函数,并且可以改变和存储函数外创建的变量的值。


>>> def knights2( saying): .



..             def inner2(): 



...                     return "We are the knights who say: '%s'" % saying 



...             return inner2 



...


注意闭包inner2和内部函数的区别:


  • inner2()直接使用外部的sanying参数,而不是通过另外一个参数获取;
  • knights2()返回为inner2函数,而不是调用它。

>>> a = knights2(' Duck') 



>>> b = knights2(' Hasenpfeffer')






#a和b既是函数也是闭包



>>> type( a) 



< class 'function'> 



>>> type( b) 



< class 'function'>





>>> a 



< function knights2.< locals>. inner2 at 0x10193e158> 



>>> b 



< function knights2.< locals>. inner2 at 0x10193e1e0>





>>> a() 



"We are the knights who say: 'Duck'" 



>>> b() 



"We are the knights who say: 'Hasenpfeffer'"



十一、匿名函数——lambda()函数 



# -*- Coding : UTF-8 -*-



#Author: Da Chen



#Date: 2018/4/2









def edit_story(words,func):



'''



words—— 单词列表;



func—— 遍历单词列表里单词的函数





'''



    for word in words:



        print (func(word))





stairs = [ 'thud' , 'meow' , 'thud' , 'hiss' ]





def enliven(word):



    return word.capitalize() + '!'





edit_story(stairs,enliven)









Thud!



Meow!



Thud!



Hiss!



如果用lambda的话,enliven()函数可以简介地用下面一个lambda代替:


>>> edit_ story( stairs, lambda word: word. capitalize() + '!' ) 



Thud! 



Meow! 



Thud! 



Hiss!



十二、生成器



生成器是用来创建Python序列的一个对象。使用它可以迭代庞大的序列,且不需要在内存中创建和存储整个序列。通常,生成器是为迭代器产生数据的。如range()。


每次迭代生成器时,它会记录上一次调用的位置,并且返回下一个值。这一点和普通的函数是不一样的,一般函数都不记录前一次调用,而且都会在函数的第一行开始执行。


如果想创建一个比较大的序列,使用生成器推倒的代码会很长,这时可以尝试写一个生成器函数。生成器函数和普通函数类似,但是它的返回值使用yield语句声明而不是return。


>>> def my_range(first=0,last=10,step=1):



...     number = first



...     while number < last:



...             yield number



...             number += step



...



>>> my_range



<function my_range at 0x7ffda0bbbea0>



>>> ranger = my_range(1,6)



>>> type(ranger)



<class 'generator'>






#生成器对象可以进行迭代



>>> for i in ranger:



...     print(i)



...



1



2



3



4



5



十三、装饰器



有时候需要在不改变源代码的情况下修改已经存在的函数。常见的例子是增加一句调试声明,以查看传入的参数 。


装饰器实质上是一个函数。它把一个函数作为输入并且返回另外一个函数。


在装饰器中,通常使用下面这些Python技巧:


  • *args和**kwargs
  • 闭包
  • 作为参数的函数

def document_func(func):



'''



定义一个装饰器,实现如下功能:



1 、打印输出函数的名称和参数的值



2 、执行含有参数的函数



3 、打印输出结果



4 、返回修改后的函数



'''



    def new_function(*args,**kwargs):



        print ( 'Running Function:' ,func. __name__ )



        print ( 'Positional arguments:' ,args)



        print ( 'Keyword arguments:' ,kwargs)



        result = func(*args,**kwargs)



        print ( 'Result:' ,result)



        return result



    return new_function



通过人工赋值来使用装饰器:


>>> def add_ ints( a, b): 



...             return a + b ... 



>>> add_ ints( 3, 5) 





>>> cooler_ add_ ints = document_ it( add_ ints) # 人工 对 装饰 器 赋值 



>>> cooler_ add_ ints( 3, 5) 



Running function: add_ ints 



Postitional arguments: (3, 5) 



Keyword arguments: {} 



Result: 8 



8


或者直接@


>>>@document_func



       def add_num(a,b):



           return a + b





>>>add_num( 2 , 8 )









Running Function: add_num



Positional arguments: (2, 8)



Keyword arguments: {}



Result: 10



同样一个函数可以有多个装饰器,靠近函数定义(def上面)的装饰器最先执行,然后依次执行上面的


>>> def square_it(func):



...     def new_function(*args,**kwargs):



...             result = func(*args,**kwargs)



...             return result * result



...     return new_function



...






#注意不同装饰器顺序导致结果的不同



>>> @document_ it 



...      @square_ it .



..       def add_ ints( a, b): 



...             return a + b 



... 



>>> add_ ints( 3, 5) 



Running function: new_ function 



Positional arguments: (3, 5) 



Keyword arguments: {} 



Result: 64 



64





>>> @square_ it 



...      @document_ it 



...      def add_ ints( a, b): 



...             return a + b 



... 



>>> add_ ints( 3, 5) 



Running function: add_ ints 



Positional arguments: (3, 5) 



Keyword arguments: {} 



Result: 8 



64



全局变量。


为了读取全局变量而不是函数中的局部变量,需要在变量前面显式地加关键字global。


>>> animal = 'fruitbat' 



>>> def change_ and_ print_ global(): 



...             global animal 



...             animal = 'wombat' 



...             print(' inside change_ and_ print_ global:', animal) 



... 



>>> animal 'fruitbat' 



>>> change_ and_ print_ global() 



inside change_ and_ print_ global: wombat 



>>> animal 



'wombat'



如果在函数中不声明关键字global,Python会使用局部命令空间,同时变量也是局部的。函数执行后回到原来的命名空间。


Python提供了两个获取命名空间内容的函数:


  • locals()返回一个局部命名空间内容的字典;
  • globals()返回一个全局命名空间内容的字典。

>>> animal = 'cat'



>>> def change_local():



...     animal = 'dog'



...     print('locals:',locals())



...



>>> animal



'cat'



>>> change_local()



locals: {'animal': 'dog'}



>>> print('globals:',globals())



globals: {'__name__': '__main__', 'run_sth_with_args': <function run_sth_with_args at 0x7ffda34417b8>, 'my_range': <function my_range at 0x7ffda0bbbea0>, 'run_with_positional_args': <function run_with_positional_args at 0x7ffda3465400>, 'run_something': <function run_something at 0x7ffda3441730>, 'time': <module 'time' (built-in)>, 'answer': <function answer at 0x7ffda34bf488>, 'players': <function players at 0x7ffda3f5c9d8>, '__builtins__': <module 'builtins' (built-in)>, 'this': <module 'this' from '/usr/lib/python3.5/this.py'>, '__spec__': None, 'sum_arg': <function sum_arg at 0x7ffda3f5cae8>, '__doc__': None, 'animal': 'cat', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'square_it': <function square_it at 0x7ffda0bbbf28>, 'add_args': <function add_args at 0x7ffda3441510>, 'ranger': <generator object my_range at 0x7ffda0b9bca8>, '__package__': None, 'change_local': <function change_local at 0x7ffda0bbc0d0>, 'i': 5}



>>> animal



'cat'



名称中_和__的用法


以两个下划线__开头和结束的名称都是Python的保留用法。因此,在自定义的变量中不能使用它们。


例如,一个函数的名称是系统变量function.__name__,它的文档字符串是function.__doc__:


>>> def amazing(): 



...             '''This is the amazing function. 



...             Want to see it again?''' 



...             print(' This function is named:', amazing.__ name__) 



...             print(' And its docstring is:', amazing.__ doc__) 



... 



>>> amazing() 



This function is named: amazing 



And its docstring is: This is the amazing function. Want to see it again?



十四、使用try和except处理错误



“Do, or do not. There is no try.”


                                                    ————Yoda


当你执行可能出错的代码时,需要适当的异常处理程序用于阻止潜在的错误发生。


在异常可能发生的地方添加异常处理程序,对于用户明确错误是一种好方法。即使不会及时解决问题,至少会记录运行环境并且停止程序执行。


>>> short_ list = [1, 2, 3] 



>>> while True: 



...             value = input(' Position [q to quit]? ')



...             if value == 'q': 



...                     break 



...             try: 



...                     position = int( value) 



...                     print( short_ list[ position]) 



...             except IndexError as err: 



...                     print(' Bad index:', position) 



...             except Exception as other: 



...                     print(' Something else broke:', other) 



... 



Position [q to quit]? 1 





Position [q to quit]? 0 





Position [q to quit]? 2 





Position [q to quit]? 3 



Bad index: 3 



Position [q to quit]? 2 





Position [q to quit]? two 



Something else broke: invalid literal for int() with base 10: 'two' 



Position [q to quit]? q



编写自己的异常:


>>> class UppercaseException(Exception):



...             pass



...



>>> words = ['eeenie','meenie','miny','MO']



>>> for word in words:



...             print(word)



...             if word.isupper():



...                     raise UppercaseException(word)



...



eeenie



meenie



miny



MO



Traceback (most recent call last):



  File "<stdin>", line 4, in <module>



__main__.UppercaseException: MO


一个异常是一个类,即类Exception的一个子类。即使没有定义UppercaseException的行为(注意到只使用pass),也可以通过继承其父类Exception在抛出异常时输出错误提示。