Python基础(第六节)

函数也是对象
定义函数时建立对象,调用函数时可以反复调用对象

变量的作用域(全局变量和局部变量)
全局变量
1、在函数和类定义之外声明的变量
2、作用域为定义的模块,从定义位置开始知道模块结束
3、全局变量降低了函数的通用性和可读性,应尽量避免全局变量的使用
4、全局变量一般作常量使用
5、函数内要改变全局变量的值,使用global声明一下

局部变量
1、在函数体中(包括形式参数)声明的变量
2、局部变量的引用比全局变量快,优先考虑使用
3、如果局部变量和全局变量同名,则在函数内部隐藏全局变量,只使用同名的局部变量

a = 100
def f1():
    global a
    a = 300

    print(a)

print(a)
f1()
运行结果为:
100
300
a = 100
def f1():
    global a
    a = 300

    print(a)
f1()
print(a)
运行结果为:
300
300

参数的传递
1、函数的参数传递本质上是从实参到形参的赋值操作
2、Python中参数的传递都是引用传递(传递地址),不是值传递
3、具体操作分为两类:
①对“可变对象”进行“写操作”,直接作用于原对象本身
②对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间

传递可变对象的引用

a = [1,2]
print(id(a))
def test01(m):
    print(id(m))
    m.append(3)
    print(id(m))
test01(a)
print(a)

运行结果为:
2333204701768
2333204701768
2333204701768
[1, 2, 3]

传递不可变对象的引用
不可变对象有:int、float、字符串、元组、布尔值

a = 1
print(id(a))
def test01(n):
    print(id(n))
    n = n+1
    print(id(n))
test01(a)

测试结果为:
140730502189888
140730502189888
140730502189920

浅拷贝和深拷贝
1、内置函数:浅拷贝copy()、深拷贝deepcopy()
2、浅拷贝:不拷贝子对象内容,只是拷贝子对象的引用
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象

#测试浅拷贝
import copy
a = [1,2,[5.6]]
b = copy.copy(a)

print("a:",a)
print("b:",b)

b.append(30)    #在b中新加了地址,指向的值为30
b[2].append(7)    #在a原来对应的地址中加入了7这个值
print("浅拷贝......")
print("a:",a)
print("b:",b)

运行结果为:
a: [1, 2, [5.6]]
b: [1, 2, [5.6]]
浅拷贝......
a: [1, 2, [5.6, 7]]
b: [1, 2, [5.6, 7], 30]
#测试深拷贝
import copy
a = [1,2,[5.6]]
b = copy.deepcopy(a)

print("a:",a)
print("b:",b)

b.append(30)    
b[2].append(7)    
print("深拷贝......")
print("a:",a)
print("b:",b)

运行结果为:
a: [1, 2, [5.6]]
b: [1, 2, [5.6]]
深拷贝......
a: [1, 2, [5.6]]
b: [1, 2, [5.6, 7], 30]

传递不可变对象是浅拷贝

#传递不可变对象时,如果发生拷贝,是浅拷贝
a = (1,2,[5,6])
print("a:",id(a))
def test01(m):
    print("m:",id(m))
    m[2][0] = 888
    print(m)
    print("m",id(m))

test01(a)
print(a)

运行结果为:
a: 2739911266808
m: 2739911266808
(1, 2, [888, 6])
m 2739911266808
(1, 2, [888, 6])

参数的几种类型
1、位置参数
函数调用时,实参数默认按位置顺序传递,需要个数与形参匹配

2、默认值参数
在定义函数时,直接给形参赋值;
调用函数时,如果没有添加实参则用默认值,添加了实参则用新添加的值

def test01(a,b,c=1,d=2):
    print(a,b,c,d)
test01(1,2)
test01(1,2,3)

运行结果为:
1 2 1 2
1 2 3 2

3、命名参数
在调用时,把名字写出来,不需要对应位置

def test01(a,b,c):
    print(a,b,c,)
test01(c=1,b=2,a=3)

运行结果为:
3 2 1

4、可变参数
1、可变参数指的是“可变数量的参数”
2、*param:将多个参数收集到一个元组对象中
3、**param:将多个参数收集到一个字典对象中

def test01(a,b,*c):
    print(a,b,c)
test01(1,2,3,4)

运行结果为:
1 2 (3, 4)
def test02(a,b,**c):
    print(a,b,c)
test02(1,2,name = 'wyj',school = 'hit')    #注意字典既要有key又要有value

运行结果为:
1 2 {'name': 'wyj', 'school': 'hit'}

5、强制命名参数
在带星号的“可变参数”后面增加新的参数时,必须是强制命名参数,否则会有歧义,报错

def test02(*a,b,c):
    print(a,b,c)
test02(1,2,b = 3,c = 4)

运行结果为:
(1, 2) 3 4

lambda表达式和匿名函数
1、lambda表达式可以用来声明匿名函数
2、lambda函数是一种简单的、在同一行中定义函数的方法
3、lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值

4、基本语法:

lambda arg1,arg2,agr3... : 表达式
>>> f = lambda a,b,c:a+b+c
>>> print(f(2,3,4))
9

把函数对象放进列表中

>>> g = [lambda a:a*2,lambda b:b*3]
>>> print(g[0](6))
12

eval()函数
将字符串str当成有效的表达式来求值并返回计算结果

语法格式:

eval(source[,globals[,locals]])

source:一个Python表达式或函数compile()返回的代码对象
globals:可选,必须是dictionary
locals:可选,任意映射对象
>>> eval("print('abcde')")
abcde
>>> a = 10
>>> b = 10
>>> c = eval("a+b")
>>> c
20
>>> a = 1
>>> b = 2
>>> dict1 = dict(a = 100,b = 200)
>>> d1 = eval("a+b")
>>> d2 = eval("a+b",dict1)
>>> print(d1,d2)
3 300

递归函数
1、自己调用自己的函数,在函数体内部直接或间接自己调用自己
2、每个递归函数必须包含两个部分
①终止条件
表示递归什么时候结束,一般用于返回值,不再调用自己
②递归步骤
把第n步的值和第n-1步相关联
3、递归函数由于会创建大量的函数对象,会过量的消耗内存和运算能力;在处理大量数据时,谨慎使用

def test01():
    print("test01")
    test02()
    
def test02():
    print("test02")

test01()

运行结果为:
test01
test02
#无终止条件,栈空间会满,报错
def test01():
    print("test01")
    test01()
def test01(n):
    print("test01",n)
    if n == 0:
        print("over")
    else:
        test01(n-1)
test01(4)

运行结果为:
test01 4
test01 3
test01 2
test01 1
test01 0
over

※※※ 函数调用时,会在栈中生成一个对象,多次调用则生成多个栈,最后对象要全部走完
※※※栈的特点:先进后出,后进先出
例子如下:

def test01(n):
    print("test01",n)
    if n == 0:
        print("over")
    else:
        test01(n-1)
    print("test01***",n)
test01(3)

运行结果:
test01 3
test01 2
test01 1
test01 0
over
test01*** 0
test01*** 1
test01*** 2
test01*** 3

※※※ 阶乘计算案例

def test01(n):
    if n == 1:
        return 1
    else:
        return n*test01(n-1)
s = test01(3)
print(s)

运行结果:
6
发布了14 篇原创文章 · 获赞 0 · 访问量 387

猜你喜欢

转载自blog.csdn.net/Bro_Jun/article/details/104784503