Python基础0227

函数

函数是组织好的、可重复使用的、实现的单一功能的代码段。函数一般都有输入(参数)和输出(返回值)。Python中函数是一等对象(first class),意味着它们可以被赋值,从其他函数返回值,并且传递函数对象。

函数定义

def func(args):
	pass

函数调用

func(args)

函数参数

def add(x,y):
	return x + y

位置参数和关键字参数

位置参数和关键字参数在调用的时候决定

def add(x,y):
	print('x={0}.format(x)')
	print('y={0}.format(y)')
	return x + y
add(1,2)
add(y=1,x=2)
add(1,x=2)
  • 位置参数 通过参数传递的位置来决定
  • 关键字参数 通过参数名称来决定
  • 混合使用 关键字参数必须在位置参数之后

默认参数

def inc(x,i=1):
	return x + i
inc(5)
inc(5,i=3)
  • 默认参数在调用的时候可以省略
  • 默认参数必须在非默认参数之后

可变参数\可变位置参数

def sum(*args):
	ret = 0
	for x in args:
		ret += x
	return ret 
  • args 将多个参数组装成一个元组
  • args 不限制参数的位置

可变关键字参数

def print_info(**kvargs):
	for k,v in kvargs.items():
		print('{0}=>{1}'.format(k,v))
print_info(a=1,b=2,c=3)
  • kvargs 将多个关键字参数组装成字典
  • 可变参数函数在定义的时候,就决定了参数是位置参数还是关键字参数
def print_info(*args,**kvargs):
	for i in args:
		print(i)
	for k,v in kvargs.items():
		print('{0}==>{1}'.format(k,v))
print_info(1,2,3,a=3,b=4)
  • 定义参数一般顺序:非默认 非可变参数 可变位置参数 可变关键字参数
  • 默认参数不要和可变参数放到一起
def print_info(x,y,*args,**kvargs):
    print('x={0}'.format(x))
    print('y={0}'.format(y))
    for i in args:
        print(i)
    for k,v in kvargs.items():
		print('{0}==>{1}'.format(k,v))
print_info(1,2,3,4,5,a=3,b=4)

参数解包

def add(x,y):
    print('x is {0}'.format(x))
    print('y is {0}'.format(y))
    return x + y
    
lst = [1,2]
add(*lst)
x is 1
y is 2
3

d={"x":1,"y":2}
add(**d)
x is 1
y is 2
3

add(*[1,2])
x is 1
y is 2
3

add(**{"x":1,"y":2})
x is 1
y is 2
3
  • 解包参数需要和函数定义的参数变量名和数量一一对应
  • *args 将收集的所有位置参数,放到一个元组中,最后将这个元组赋值给args
  • **kvargs将收集的所有关键字参数,放到一个字典中,最后将这个字典赋值给kvargs
  • 收集参数,形参中利用***实现
  • 参数解包,实参中利用***实现
def mymap(func,*seqs):      #封装成元组 * 收集参数
  	res=[]
  	print(seqs)             #封装后的元组
  	for args in zip(*seqs): #zip函数接受 seqs元组解包后的列表(可迭代对象),每次返回一个元组对象。 * 解包参数  
      	res.append(func(*args))  # * 解包参数 args是zip返回的元组对象
  	return res
print(mymap(abs,[-2,-1,0,1,2]))
([-2, -1, 0, 1, 2],) #列表整体会被当成一个参数
[2, 1, 0, 1, 2]

默认参数的坑

def fn(lst=[]):
	print(id(lst))
	lst.append(1)
	print(lst)
fn()
4442085896
[1]
fn()
4442085896
[1, 1]

默认参数不是赋值,而是指向一个函数内部新的对象,对这个对象的任何修改都会改变引用它的初始值。因此默认参数通常指向不可变对象。

def fn(lst='None'):
	if lst is None:
		lst=[]
  	lst.append(1)
  	print(id(lst))
  	print(lst)

未定义lst时,每次执行函数都指向一个新的空列表对象(id不一样)。

函数返回值

  • 使用return关键字返回
  • 可以返回任何对象
  • 可以通过解包变相返回多值
  • 默认返回None
def fn():
	pass
type(fn())
NoneType

def fn():	
	return 1,2,3,4

fn()
(1, 2, 3, 4)
type(fn())
tuple

def fn()
	for i in range(5):
		print(i)
		if i > 2:
			return            

fn()
0
1
2
3

type(fn())
0
1
2
3
NoneType

递归函数

python中尽量避免使用递归,最大递归深度小于1000,实际测试大于998之后就会报错。

def func(x):
   	if x > 1:
    	return func(x-1)*x
   	else:
       	return 1
等价于
a=1
for i in range(1):
	a=a*i
print(a)

变量作用域

作用域是指变量在程序中的可见范围,变量的作用域通常就是定义他们的代码块。

  • 局部变量:在函数体内定义的变量,其作用域为函数体内部,和函数体外的参数没有关系。
  • 全局变量:定义在函数体外的变量,对全局可见的变量,函数体内也可继承这个变量。

不建议使用 global语句可以在函数体内定义全局变量,之后对变量的操作都是对全局变量的操作。

x = 50
def func():
    global x
    x = 2
    print(x)

func()
print(x)
2
2

globals() 可用全局变量

locals() 可用本地变量

函数调用过程

可以参考什么是堆和栈,它们在哪儿?

生成器

def fun():
	i = 1
	print("I am fun")
	while i < 6:
		yield i
		print("I am yield")
		i = i + 1

def main():
	print("I am main")
	for i in fun():
		print("i")
		print("I am for_loc")

main()

print("===")

def main1():
	print("I am main1")
	if 1 in fun():        #条件加次数限制的循环,多次执行生成器直至命中或次数耗净。
		print("Y")
		print("I am for_loc")

main1()

I am main 			 
I am fun         #开始调用函数fun 
i                #yield返回i给主函数main的for循环,并暂存fun函数
I am for_loc	 #main函数循环体执行完成,并再次指向函数fun 
I am yield       #从上次暂存点继续执行fun函数 
i                #while循环满足再次遇到yield,暂存fun函数,返回i给main函数
I am for_loc
I am yield
i
I am for_loc
I am yield
i
I am for_loc
I am yield
i
I am for_loc     #main函数循环体执行完成,并再次指向函数fun
I am yield		 #从上次暂存点继续执行fun函数
===				 #while条件不满足,fun结束,返回None给for循环,main函数结束	
I am main1
I am fun
Y
I am for_loc

能让生成器遍历其中元素的,除了for循环之外,还可以使用if in成员判断。

惰性求值

def fun(x):
    a = 1
    for i in range(1,x+1):
    	a = a * i 
      	yield a

fun(5)
<generator object fun at 0x7ff016f1f3a8>

next(fun(5))
1
next(fun(5))
1              # 每次调用迭代器本身,都从新开始,没有状态保持。

it = fun(5)
next(it)
1
next(it)
2			   # 赋值引用之后,迭代器对象确定之后,每次执行都保存上一次的值。
posted @ 2016-02-27 01:55  蓝色骨头  阅读(194)  评论(0)    收藏  举报