当先锋百科网

首页 1 2 3 4 5 6 7

1函数概述1)数学定义 y=f(x) ,y是x的函数,x是自变量

2)Python函数:若干语句组成的语句块、函数名称、参数列表构成,它是组织代码的最小单元

完成一定的功能

2 函数的作用:结构化变成对代码的最基本封装,一般按照功能组织一段代码;封装的目的是为了复用,减少冗余代码;

代码更加简洁美观,可读易懂;

3 内建函数

python中提供很多内建函数,可以直接拿来使用,下表列举了一些函数作用id()返回变量id

hast()返回对象的hash值

type()返回对象的类型

input()获取用户输入信息

print()打印输出信息

len(s)返回一个集合类型的元素个数

isinstance(obj, class_or_tuple)判断对象obj是否属于某种类型,返回bool类型

issubclass(cls, class_or_tuple)判断类型cls是否是某种类的子类,返回bool

float() int() bin() hex() oct() bool() list() tuple() dict() set() complex() bytes() bytearray()类型转换

enumerate(seq, start=0)返回索引数字和序列元素的二元组

示例str_1 = "hello world"

print(id(str_1))

print(hash(str_1))

print(type(str_1))

4 函数的定义:def 函数名(参数列表):

函数体(代码块)

[return 返回值]函数名必须是合法标识符,约定见名知意,尽量使用英文缩写

语句块必须缩进,约定4个空格

python的函数若不写return语句,默认返回一个None值

函数定义的参数列表成为形式参数,只是一种符号表达,简称形参

调用:

函数定义,只是声明了一个函数,它不会被执行,需要调用

调用的方式,就是函数名加上小括号,括号内写上参数。

调用时写的参数就是实际参数,为实参

示例def add(x:int, y:int) -> int:

""" 执行两个数的加法的函数"""

return x+y

# 调用

sum = add(10, 16)

print(sum)

5 函数的参数

参数调用时,传入的参数个数要和定义的个数相匹配(可变参数例外)位置参数:

示例:def fun(x ,y, z):

max_num = max(x, y, z)

print(max_num)

# 位置参数,调用时按照定义的顺序传入实参。

fun(10, 20, 30)关键字参数:

示例:def fun(x ,y, z):

result = z -x -y

print(result)

# 传参方式

fun(x=10, y=20, z=30)

# 可以改变传参顺序

fun(y=20, x=10, z=30)

# 关键字参数传参要在位置参数之前,位置的参数是按照位置对应的。

fun(10, z=30, y=20)参数默认值:

定义时,在形参后跟一个值

示例:

示例:def fun(x=1 ,y=2, z=3):

result = z -x -y

print(result)可变参数:

一个形参可以匹配任意个参数

位置参数的可变参数:def add(*nums):

sum = 0

print(type(nums))

for x in nums:

sum+=x

print(sum)

在形参前加*表示该参数是可变参数,可以接收多个实参,收集多个实参为一个tuple,通常为使用*args可变关键字参数:def showconfig(**kwargs):

for k, v in kwargs.items():

print('{}={}'.format(k,v))

# 形参使用**符号,表示可接收多个关键字参数

# 收集的实参名称和值组成一个字典

# 可变参数混合使用:

def showconfig(username, password, **kwargs):

pass

def showconfig(username, *args, **kwargs):

pass参数总结:

参数列表一般顺序是普通参数、缺省参数,可变位置参数,keyword-only参数,可变关键字参数.参数解构

举例:def add(x, y):

return x+y

add(4,5) #直接调用

t = (4,5)

add(*t)

add(*range(1,3)) #同样可以使用可迭代对象传参

# 前提是参数个数相同

6作用域:

一个标识符的可见范围,一般常说是变量的作用域。全局作用域:

在整个运行环境中都可见

局部作用域:

在局部变量使用范围不能超过其所在的局部范围

示例:x = 5

def foo():

y = x + 1

x += 1 #错误,赋值即定义,相当于x未定义就直接使用

print(x)全局变量globalx = 5

def foo():

global x

x += 1

print(x)

foo()闭包

自由变量:未在本地作用域中定义的变量。例如定义在内存函数外的外层函数中作用域的变量。

闭包:就是一个概念,出现在嵌套函数中,指的是内层函数引用了外层函数的自由变量,就形成了闭包。def counter():

c = [0]

def inc():

c[0] += 1 # 这里不会报错,因为是c[0] 而不是c,这是对c中的元素重新赋值

return c[0]

return inc #返回是的一个函数引用,而不是函数调用

foo = counter()

print(foo(), foo()) #打印1和2

c = 100

print(foo()) #打印3

上面是python2中实现闭包的方式,Python3中还可以使用关键字nonlocaldef counter():

c = 1

def innter():

nonlocal c

c += 1

return c

return innter

foo = counter()

print(foo(), foo())

c = 100

print(foo())

nonlocal关键字:将变量标记为在上级的局部作用域定义,但不能是全局作用域中定义。默认值的作用域def foo(l=[]):

l.append(1)

print(l)

foo() #打印[1]

foo() #打印[1,1]

#原因是函数也是对象,python把函数的对象的默认值放在了属性中,这个属性就伴随着这个函数对象的整个生命周期

查看foo.__defaults__def foo(l=[], u='abc', z=123):

l.append(1)

print(l)

print(foo(), id(foo))

print(foo.__defaults__)

print(foo(), id(foo))

print(foo.__defaults__)

# 函数两次打印id相同,表明函数地址没有发生改变,就是说函数这个对象没有变,调用它,它的属性__defaults__中使用元组保存所有默认值。

# 其中l默认值是引用类型,引用类型元素变动,并不是元组的变化

非引用类型中def foo(l=1, u='abc', z=123):

u = ‘xyz’

z = 789

print(l, u, z)

print(foo.__defaults__) #打印(1, 'abc', '123')

print(foo(), id(foo))

print(foo.__defaults__) #打印(1, 'abc', '123')

可变类型默认值,如果使用这个默认值,就可能修改这个默认值

有时候这个特性是好的,有的时候这种特性是不好的,也会带来一些麻烦

如何做到按需修改?看下面这两种方法def foo(x=[], u='abc', z=123):

x = x[:]

x.append(1)

print(x)

foo()

print(foo.__defaults__)

foo()

print(foo.__defaults__)

foo([10])

print(foo.__defaults__)

foo([10,5])

print(foo.__defaults__)def foo(x=None, u='abc', z=123):

if x is None:

x = []

x.append(1)

print(x)

foo()

print(foo.__defaults__)

foo()

lst=[10]

foo(lst)

print(lst) #lst发生改变

print(foo.__defaults__)

foo([10,5])

print(foo.__defaults__)

一般函数中不使用打印语句,结尾使用return

第一种方法:

使用影子拷贝创建一个新的对象,永远不能改变传入的参数。

第二种方法:

通过值的判断就可以灵活的选择创建或者修改传入对象。

这种方式灵活,应用广泛。

很多函数的定义,都可以看到使用None这个不可变的值作为默认参数,这是一种惯用法。

7函数的销毁全局函数

1)重新定义同名函数

2)del 语句

3)程序结束时

局部函数

1)重新定义同名函数

2)del 语句

3)上级作用域销毁

8 变量名解析原则LEGB

1)Local:本地作用域,局部作用域的local命名空间,函数调用时创建,调用结束消亡

2)Enclosing:Python2.2引入了嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间

3)GLobal,全局作用域,一个模块的命名空间,模块被导入时创建,解释器退出时消亡

4)Build-in,内置模块的命名空间,生命周期,从Python解释器启动时创建到解释器退出时消亡

9 递归函数递归Recursion:

函数直接或者间接调用自身就是递归

递归需要有边界、递归前进段、递归返回段

递归一定要有边界条件

当边界条件不满足的时候,递归前进

当边界条件满足的时候,递归返回间接递归

是通过别的函数调用了函数自身。

但是构成了循环递归调用是非常危险的,但是往往这种情况在代码复杂的情况下,还是可能发生这种调用。要用代码规范来避免这种递归调用的发生。

注意:慎用递归递归一定要有退出条件,递归调用定要执行到这个退出条件。

递归调用深度不宜过深

查看递归限制层数:import sys

print(sys.getrecursionlimit())递归的性能:

循环稍微复杂一些,但只要不是死循环,可以多次迭代直至算出结果。

递归函数代码精简易懂,但是只能获取到最外层的函数滴啊用,内部递归结果都是中间结果。而且给定一个n都要进行2n次递归,深度越深,效率越低。

递归示例:

求n的阶乘def fun(n):

if n == 1:

return 1

return n*fun(n-1)

print(fun(3))

10 匿名函数:Python借助lambda表达式构建匿名函数

格式:

lambad 参数列表:表达式lambda x:x*2

(lambda x:x*2)(4) #调用

foo = lambda x,y:(x+y)**2

foo(2,1)用途:

高阶函数传参时,使用lambda表达式,往往能简化代码

11Python生成器函数生成器generator

生成器是指生成器对象,可以由生成器表达式得到,也可以用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象

生成器函数:

1)函数体中包含yield语句的函数,返回生成器对象

2)生成器对象,是一个可迭代对象,也是迭代器

3)生成器对象,延迟计算,惰性求值

4)普通函数调用fn(),函数会立即执行完毕,但是生成器函数可以使用next函数多次执行

生成器函数等价于生成器对象,只不过生成器函数可以更加复杂。

示例def gen():

print("line 1")

yield 1

print("line 2")

yield 2

print("line 3")

return 3

next(gen()) #line 1

next(gen()) #line 1

g = gen()

print(next(g)) #line1

print(next(g)) #1ine2

print(next(g)) #line 3 StopIteration

print(next(g,'End')) #生成器到尾了,返回默认值‘End’