函数是组织好,可重复使用,用来实现单一或相关联功能的代码段,能提升应用的模块性和代码的重复利用率。
Python提供了许多内建函数,好比print()。
也能够本身建立函数,被叫作用户自定义函数。python
规则:express
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。 任何传入参数和自变量必须放在圆括号中间。圆括号之间能够用于定义参数。 函数的第一行语句能够选择性地使用文档字符串—用于存放函数说明。 函数内容以冒号起始,而且缩进。 return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return至关于返回 None。
语法:vim
def functionname( parameters ): "函数_文档字符串" function_suite return [expression]
例:
#!/usr/bin/python
def printme( str ): # 定义函数
"打印任何传入的字符串"
print str
returnapp
printme("我要调用用户自定义函数!") printme("再次调用同一函数") 以上实例输出结果: 我要调用用户自定义函数! 再次调用同一函数
全部参数在Python里都是按引用传递。若是你在函数里修改了参数,那么在调用这个函数的 函数里,原始的参数也被改变了。
例:
#!/usr/bin/python
def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4]);
print "函数内取值: ", mylist
returnide
# 调用changeme函数 mylist = [10,20,30]; changeme( mylist ); print "函数外取值: ",mylist 传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果以下: 函数内取值: [10, 20, 30, [1, 2, 3, 4]] 函数外取值: [10, 20, 30, [1, 2, 3, 4]]
咱们在使用def 关键字定义一个函数时,其后必须跟有函数名和包括形式参数的圆括号。函数体的下一行开始,必须是缩进的。函数体的第一行能够是字符串,这个字符串就是文档字符串documentation string,一般也称做:docstring函数
在函数体的第一行,可使用一对三引号(''')或者(""")来定义文档字符串,文档字符串一般第一行以大写字母开头,以句号 (.)结束,第二行是空行,第三行开始是详细描述。强烈建议为你重要的函数写文档字符串都遵循此惯例。
工具
文档字符串是使用Python过程当中一个很重要的工具,他对程序文档颇有帮助,使程序很容易理解。甚至当程序运行的时候,能够从一个函数中返回文档字符串。把函数当作一个对象来看,这更有助于咱们的理解,就至关于获取一个对象的属性(__doc__).
ui
#cat nester.py 这是一个模块文件 #!/usr/bin/env python3 "这是模块文档字符串" def print_list(name): '''这是函数文档字符串''' for each_item in name: if isinstance(each_item,list): print_list(each_item) else: print each_item #python >>> import nester >>> print nester.print_list.__doc__ 这是函数文档字符串 >>> help(nester) Help on module nester: NAME nester - 这是模块文档字符串 FILE /python/nester.py FUNCTIONS print_list(name) 这是函数文档字符串 (END)
调用函数时可以使用的参数类型:
• 必备参数
• 关键字参数
• 默认参数
• 不定长参数debug
必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的同样。
好比调用printme()函数,你必须传入一个参数,否则会出现语法错误:
#!/usr/bin/python
def printme( str ):
print str;
return;日志
#调用printme函数 printme();
输出结果:
Traceback (most recent call last):
File "test.py", line 11, in <module>
printme();
TypeError: printme() takes exactly 1 argument (0 given)
关键字参数和函数调用关系紧密,函数调用使用关键字参数来肯定传入的参数值。
使用关键字参数容许函数调用时参数的顺序与声明时不一致,由于 Python 解释器可以用参数名匹配
参数值。
如下实例在函数 printme() 调用时使用参数名:
#!/usr/bin/python3
def printme( str ):
print str;
return;
#调用printme函数 printme( str = "My string"); 输出结果: My string
下例能将关键字参数顺序不重要展现得更清楚:
#!/usr/bin/python3
def printinfo( name, age ):
print "Name: ", name;
print "Age ", age;
return;
#调用printinfo函数 printinfo( age=50, name="miki" ) 输出结果: Name: miki Age 50
调用函数时,缺省参数的值若是没有传入,则被认为是默认值。
下例会打印默认的age,若是age没有被传入:
#!/usr/bin/python3
def printinfo( name, age = 35 ):
print "Name: ", name;
print "Age ", age;
return;
#调用printinfo函数 printinfo( age=50, name="miki" ); printinfo( name="miki" ) 输出结果: Name: miki Age 50 Name: miki Age 35
若是须要一个函数能处理比当初声明时更多的参数。这些参数叫作不定长参数,和上述2种参数不
同,声明时不会命名。
语法:
def functionname([formal_args,] var_args_tuple ):
function_suite
return [expression]
#加了星号()的变量名会存放全部未命名的变量参数。
例1:
#!/usr/bin/python3
def printinfo( arg1, *vartuple ):
print "输出: "
print arg1
for var in vartuple:
print var
return
# 调用printinfo 函数 printinfo( 10 ); printinfo( 70, 60, 50 ) 输出结果: 输出: 10 输出: 70 60 50
例2:
#vim multi.py
def multiarg(*args):
for i in args:
print i
return
def multiargs(*args): print args[2] return print "第一个调用:" multiarg('hello','lili','tom','wing') print "第2个调用:" multiargs('hello','lili','tom','wing') 执行结果: 第一个调用: hello lili tom wing 第2个调用: tom
*args和**kwargs
[wing@macserver ~]$ cat b.py #!/usr/bin/env python def foo(*args,**kwargs): print 'args = ',args print 'kwargs = ',kwargs print '-'*20 if __name__ == '__main__': foo(1,2,3,4) foo(a=1,b=2,c=3) foo(1,2,3,4,a=1,b=2,c=3) #同时使用*args和**kwargs,必须*args参数列在前 foo('a',1,None,a=1,b='2',c=3) #*args是一个tuple,**kwargs表示关键字参数,是一个dict 执行结果: [wing@macserver ~]$ python b.py args = (1, 2, 3, 4) kwargs = {} -------------------- args = () kwargs = {'a': 1, 'c': 3, 'b': 2} -------------------- args = (1, 2, 3, 4) kwargs = {'a': 1, 'c': 3, 'b': 2} -------------------- args = ('a', 1, None) kwargs = {'a': 1, 'c': 3, 'b': '2'} --------------------
return [表达式] 用来退出函数,选择性地向调用方返回一个表达式。
不带参数值的return语句返回None
例:
#!/usr/bin/python3
def sum( arg1, arg2 ):
total = arg1 + arg2
return total
# 调用sum函数 print sum( 10, 20 ) 输出结果: 30
一个程序全部的变量并非在任何位置均可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的做用域决定了在哪一部分程序你能够访问哪一个特定的变量名称。
调用函数时,全部在函数内声明的变量名称都将被加入到做用域中
两种最基本的变量做用域:全局变量和局部变量
定义在函数内部的变量拥有一个局部做用域
定义在函数外的变量拥有全局做用域
局部变量只能在其被声明的函数内部访问
全局变量能够在整个程序范围内访问
例:
#!/usr/bin/python
total = 0 # 这是一个全局变量
def sum( arg1, arg2 ):
total = arg1 + arg2 # total在这里是局部变量.
print "函数内是局部变量 : ", total
return total;
#调用sum函数 sum( 10, 20 ); print "函数外是全局变量 : ",total 输出结果: 函数内是局部变量 : 30 函数外是全局变量 : 0
变量:
是拥有匹配对象的名字(标识符)。
命名空间:
是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。
1.一个Python表达式能够访问局部命名空间和全局命名空间里的变量。
2.若是一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。
3.每一个函数都有本身的命名空间。类的方法的做用域规则和一般函数的同样。
4.Python认为任何在函数内赋值的变量都是局部的。所以,若是要给全局变量在一个函数里赋
值,必须使用global语句。
global VarName表达式会告诉Python, VarName是一个全局变量,这样Python就不会在
局部命名空间里寻找这个变量了。
例如,在全局命名空间里定义一个变量money,再在函数内给变量money赋值,而后Python
会假定money是一个局部变量。然而,咱们并无在访问前声明一个局部变量money,结
果就是会出现一个UnboundLocalError的错误。取消global语句的注释就能解决这个问题。
#!/usr/bin/python
Money = 2000
def AddMoney():
#想改正代码就取消如下注释:
#global Money
Money = Money + 1
print Money
AddMoney()
print Money
根据调用地方的不一样,globals()和locals()函数可被用来返回全局和局部命名空间里的名字。
在函数内部调用locals():
返回的是全部能在该函数里访问的命名。
在函数内部调用globals():
返回的是全部在该函数里能访问的全局名字。
两个函数的返回类型都是字典。因此名字们能用keys()函数摘取。
python 使用 lambda 来建立匿名函数。
• 匿名是由于不须要以标准的方式来声明,好比说, 使用 def 语句。
• 一个完整的 lambda“语句”表明了一个表达式,这个表达式的定义体必须和声明放在同一行。
• lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
• lambda函数拥有本身的命名空间,且不能访问自有参数列表以外或全局命名空间里的参数。
• lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增长运行效率。
语法:
lambda [arg1 [,arg2,.....argn]]:expression
参数是可选的,若是使用参数,参数一般也是表达式的一部分。
例:
#!/usr/bin/python
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数 print "相加后的值为 : ", sum( 10, 20 ) print "相加后的值为 : ", sum( 20, 20 ) 输出结果: 相加后的值为 : 30 相加后的值为 : 40
复习下单行语句:
def true():
return True
上面的函数没有带任何的参数而且老是返回 True。python 中单行函数能够和标题写在同一行。
重写true()函数: def true(): return True
使用 lambda 的等价表达式(没有参数,返回一个 True)为:
lambda :True
In [4]: a = lambda x, y=2: x + y In [5]: a(5) Out[5]: 7 In [6]: a(3,5) Out[6]: 8 In [2]: a=lambda *z:z In [3]: a(1,2,3,4) Out[3]: (1, 2, 3, 4)
In [1]: def hello(a,b): #函数定义
...: print a + b
...:
In [2]: hello(1,2) #函数调用,带括号表示告诉编译器”执行这个函数“
In [6]: c=hello #不带括号表示把函数赋给另外一个函数对象
In [8]: c(3,4)
7
递归函数不须要任何修改就能够处理任意深度的嵌套列表
#!/usr/bin/env python name=['wing',['tom',['jim',['lilei','han×××']]]] def print_list(name): for each_item in name: if isinstance(each_item,list): print_list(each_item) else: print each_item print_list(name) def print_list(list_name,level=0): for each_item in list_name: if isinstance(each_item,list): print_list(each_item,level+1) else: for tab_num in range(level): print "\t", print each_item print_list(name)
题目:利用递归方法求5!。 程序分析:递归公式:fn=fn_1*4! 程序源代码: #!/usr/bin/python # -*- coding: UTF-8 -*- def fact(j): sum = 0 if j == 0: sum = 1 else: sum = j * fact(j - 1) return sum for i in range(5): print '%d! = %d' % (i,fact(i)) 以上实例输出结果为: 0! = 1 1! = 1 2! = 2 3! = 6 4! = 24
Python中,按照对象是否可变,将类型分类为:
不可变类型:
对象的内容不可以改变(not mutable),这些类型中主要有数值类型(整数,浮点数,复数),字符
串类型,元组等
可变类型:
对象的内容可以改变(mutable),主要有列表,字典
Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来讲的,后面学
习到包package时,将会介绍),
这些内建函数功用在于其每每可对多种类型对象进行相似的操做,即多种类型对象的共有的操做;
若是某种操做只对特殊的某一类对象可行,Python常将其设置为该种类型的方法(method)
内建函数的查看 经过在python交互模式下,键入相应的命令便可查看当前python版本的一些内建函数 >>> dir(__builtins__) ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip'] 也能够经过以下方式查看: >>> import __builtin__ >>>dir(__builtin__)
获取内建函数帮助:
help()
获取帮助信息
其完整的通常使用形式为:
help(module.class.function)
例子:
In [3]: import sys
In [4]: help(sys.getsizeof)
数值类型表示的内建函数 bin() 获取一个整数(int类型或长整型),返回其2进制形式的字符串 oct() 获取一个整数,返回其8进制形式的字符串 hex() 获取一个整数,返回其16进制形式的字符串
对象生成的内建函数
int() 将数值或字符串转换为整数int,完整使用形式int(x,base),base用于指定进制
long() 将数值或字符串转换为整数long,完整使用形式long(x, base),base用于指定进制
float() 将数值或字符串转换为浮点数
complex()返回一个复数,完整使用形式 complex(real,imag)
str() 将所给对象转换为字符串,使用形式为str(object)
list() 获取对象,转换为列表, list(object)
dict() 获取映射转换为字典,dict(mapping)
tuple() 获取一个可迭代的对象,返回一个元组, tuple(iterable)
注:这里留意dict()内建函数建立字典的不一样方式
装饰器是咱们如今碰到的难点之一,不大好理解,能够简单的认为装饰器就是为了给函数添加额外的功能,而不用每次都手写那个功能,只须要用"@装饰器名称"调用就能够了
不使用装饰器给函数添加一个额外的功能:
下例中是给foo函数添加日志功能
#!/usr/bin/env python3 import logging def foo(): print "hello world" def use_logging(func): logging.warn("%s is running" % func.__name__) func() use_logging(foo) #每次执行foo的时候都得调用use_logging函数
使用装饰器:
@use_logging #装饰器
foo()
简陋写法:由于不能给带有参数的函数装饰,因此简陋 #!/usr/bin/env python #coding=utf8 import logging def use_logging(func): logging.warn("%s is running" % func.__name__) return func @use_logging def foo(): print "hello world" foo() 标准写法: #!/usr/bin/env python #coding=utf8 import logging def use_logging(func): def wrapper(*args,**kw): logging.warn("%s is running" % func.__name__) return func() return wrapper @use_logging def foo(): print "hello world" foo() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 带参数: #!/usr/bin/env python #coding=utf8 import logging def use_logging(func): def wrapper(*args,**kw): logging.warn("%s is running" % func.__name__) return func() #会报错 return wrapper @use_logging def foo(arg1,arg2): print "arg1+arg2=%s" % (arg1+arg2) foo(5,3) 正确写法以下: #!/usr/bin/env python #coding=utf8 import logging def use_logging(func): def wrapper(*args,**kw): logging.warn("%s is running" % func.__name__) return func(*args,**kw) return wrapper @use_logging def foo(*args,**kw): print "arg1+arg2=%s" % (args[0]+args[1]) print "hello world" foo(1,2) 由于装饰器会先执行,在没有wrapper函数的状况下return func(*args,**kw)会出现args未定义错误