Python基础学习-函数

内存分析

#测试函数也是对象
def test():
    print("wjwjwj")
test()
a=test
a()
print(id(test))
print(id(a))
print(type(a))
wjwjwj
wjwjwj
1567616045128
1567616045128
<class 'function'>

变量的作用域(全局变量和局部变量)

变量起作用的范围成为变量的作用域,不同作用域内同名变量互不影响。变量分为:全局变量,局部变量。

全局变量

  • 在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始直到模块结束。
  • 全局变量降低了函数的通用性和可读性。应尽量避免全局变量的使用。
  • 全局变量一般做常量使用。
  • 函数内要改变全局变量的值,使用global声明一下。

局部变量:

  • 在函数体中(包含形式参数)声明的变量。
  • 局部变量的引用比全局变量快,优先考虑使用。
  • 如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量。
#测试全局变量、局部变量
a=3 #全局变量
def r():
    b=4 #局部变量
    print(b)
    global a    #如果要在函数内改变全局变量的值,增加global关键字申明
    a=10
r()
print(a)
4
10

全局变量与局部变量的效率测试

局部变量的查询与访问速度比全局变量快,优先考虑使用,尤其在循环的时候。
在特别强调效率的地方或者循环次数较多的地方,可以通过将全局变量转为局部变量提高运行速度。

@author: ramon
@file: function_6.py
@time: 2020/12/10
@desc:
"""
# 测试局部变量、全局变量的效率
#全局
import math
import time
def test1():
    start=time.time()
    for i in range(10000000):
        math.sqrt(30)
    end=time.time()
    print("耗时{0}".format((end-start)))
#局部
def test2():
    b=math.sqrt
    start=time.time()
    for i in range(10000000):
        b(30)
    end=time.time()
    print("耗时{0}".format((end-start)))
test1()
test2()
耗时1.2386553287506104
耗时0.8766887187957764

参数的传递

  • 可变对象有:字典、列表、集合、自定义的对象等。
  • 不可变的对象有:数字、字符串、元组、布尔值、function等。

传递可变对象的引用

传递参数是可变对象,实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。

b=[30,60,90]
print(id(b))
print(b)
print("************************")
def test1(v): 
    print(id(v)) #b和m是同一个对象
    v.append(900)#由于m是可变对象,不创建对象拷贝,直接修改这个对象
    print(id(v))
test1(b)
print(b)
2815486677448
[30, 60, 90]
************************
2815486677448
2815486677448
[30, 60, 90, 900]

传递不可变对象的引用

传递参数是不可变对象,实际传递的还是对象的引用。在“赋值操作”时,由于不可变对象无法修改,系统会创建一个对象。

#传递不可变对象时,不可变对象里面包含的子对象是可变的。则方法内修改了这个可变对象,
a=(10,20,30,[6,8])
print("a",id(a))
def test(m):
    print("m",id(m))
    m[3][1]=10
    print(m)
    print("m",id(m))
test(a)
a 2308663109496
m 2308663109496
(10, 20, 30, [6, 10])
m 2308663109496

浅拷贝和深拷贝

为了更深入的了解参数传递的底层原理,我们需要讲解一下”浅拷贝和深拷贝”。我们可以使用内置函数:copy(浅拷贝)、deepcopy(深拷贝)。
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用
深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响对象

b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。
在这里插入图片描述
b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
在这里插入图片描述

# 测试浅拷贝和深拷贝
#先引入模块
import copy
def testCopy():
    '''测试浅拷贝'''
    a=[10,20,[7.8]]
    b=copy.copy(a)
    print("a",a)
    print("b",b)
    print("测试1***************")
    b.append(40)
    b[2].append(10)
    print("a",a)
    print("b",b)

def testdeepCopy():
    '''测试深拷贝'''
    a=[10,20,[7.8]]
    b=copy.deepcopy(a)
    print("a",a)
    print("b",b)
    print("测试2***************")
    b.append(40)
    b[2].append(10)
    print("a",a)
    print("b",b)
testCopy()
print()
testdeepCopy()
a [10, 20, [7.8]]
b [10, 20, [7.8]]
测试1***************
a [10, 20, [7.8, 10]]
b [10, 20, [7.8, 10], 40]

a [10, 20, [7.8]]
b [10, 20, [7.8]]
测试2***************
a [10, 20, [7.8]]
b [10, 20, [7.8, 10], 40]

可变参数

**可变参数指的是"可变数量的参数"。分两种情况:

  • *param(一个星号),将多个参数收集到一个“元组”对象中。
  • **param(两个星号),将多个参数收集到一个"字典"对象中。
def test01(a,b,*c):
    print(a,b,c)
test01(6,7,10,12)

def test02(a,b,**c):
    print(a,b,c)
test02(15,16,name='yxy',age=28)

def test03(a,b,*c,**d):
    print(a,b,c,d)
test03(20,21,91,92,94,name='yxy',age=28)
6 7 (10, 12)
15 16 {'name': 'yxy', 'age': 28}
20 21 (91, 92, 94) {'name': 'yxy', 'age': 28}

lambda 表达式和匿名函数

  • lambda表达式可以用来声明匿名函数。lambda函数是一个简单的、在同一行中定义函数的方法。lambda函数实际生成了一个函数对象。
  • lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
    基本语法如下:
    lambda arg1 ,arg2,arg3…:<表达式>
    arg1/arg2/arg3为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。
#测试lambda表达式、匿名函数
x=lambda a,b,c,d:a*b*c*d
print(x(6,7,8,9 ))
#列表
y=[lambda a:a*5,lambda b:b*6,lambda c:c*7]
print(y[0](10),y[1](12),y[2](14))
3024
50 72 98

eval()函数的应用

#测试eval()函数
z="print('abcde')"
eval(z)

a=5
b=8
c=eval("a+b")
print(c)
#创建字典测试
dicts=dict(a=30,b=60)
y=eval("b/a",dicts)
print(y)
abcde
13
2.0

递归函数

递归函数就是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己,总分为两个部分:

  • 终止条件
    • 表示递归什么时候结束。一般用于返回值,不再调用自己。
  • 递归步骤
    • 把第n步的值和第n-1步相关联。
#测试递归函数的基本原理
def test01(m):
    print("test01:",m)
    if m==0:
        print("over!")
    else:
        test01(m-1)
    print("test01***",m)
test01(5)
test01: 5
test01: 4
test01: 3
test01: 2
test01: 1
test01: 0
over!
test01*** 0
test01*** 1
test01*** 2
test01*** 3
test01*** 4
test01*** 5

阶乘练习

#使用递归函数,计算阶乘
def mathid(m):
    if m==1:
        return 1
    else:
        return m*mathid(m-1)
result=mathid(8)
print(result)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值