python中栈的常见函数_Python函数基础,python,基本知识

一,函数的内部底层结构

函数的变量名(标识符)存储在栈内存,其内放的位于堆内存中的函数信息的地址

所以说,有如下情况:

def fun():

print('1')

fun()

c=fun

c()

print(fun)

print(id(fun))

print(c)

print(id(c))

结果为:

1

1

1446531968888

1446531968888

可以看出,print(fun)这条命令打印的就是对应堆内存内的地址。id(fun)同样对应的是堆内存中地址。变量没有地址。

二,变量的作用域

1,全局变量:在函数和类定义之外声明的变量,作用域为模块,它降低函数的通用性与可读性,尽量避免使用。函数中要改变全局变量的值,使用golbal声明。

2,局部变量:在函数体中声明的变量,若与全局变量重名,优先使用局部变量。

代码如下:

a=3

def text():

b=4

print(b)

#print(a) #默认局部变量a,在下面会赋值a,所以有错误

global a #在函数中改变全局变量

a=300

print(a)

print(locals())#打印所有局部变量

print(globals())#打印所有全局变量

text()

print(a)

结果如下:

4

300

{'b': 4}

{'__name__': '__main__', '__doc__': '\n@author: lhy\n@file: mypy09.py\n@time: 2020/02/29\n@desc:\n', '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object at>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'D:/PycharmProjects/MyTest/mypy09.py', '__cached__': None, 'a': 300, 'text': }

300

3,变量底层结构

局部变量的地址存放在栈帧中,栈帧在调用函数时创建,在调用结束后自动销毁,空间相对独立,所以内部可以调用全局变量,但是在函数外调用不了局部变量。栈帧中保存的是函数调用本次的信息。(从堆地址的内容中取出来?)

4,局部变量与全局变量效率测试

代码如下:

import time

import math

start=time.time()

def text():

for i in range(10000000):

math.sqrt(30)

text()

end=time.time()

print('耗时为{0}'.format(end-start))

start=time.time()

def text1():

b=math.sqrt

for i in range(10000000):

b(30)

text1()

end=time.time()

print('耗时为{0}'.format(end-start))

结果如下:

耗时为2.0674610137939453

耗时为1.566443920135498

三,参数的传递

1,可变对象的传递:直接将a中id传给栈帧中形式参数m,两者指定同一地址,由于可变对象,所以直接修改。

2,不可变对象的传递:首先直接将a中id传给栈帧中形式参数m,两者指定同一地址,但是由于对象不可变,所以要改变m的值时,只能在堆中重新创建一个对象,并将新地址传给m。

代码如下:

a=[10,20]

print(id(a))

def text(m):

print(id(m))

m.append(30)

print(id(m))

text(a)

print(a)

#不可变参数

a=100

print(id(a))

def text(m):

print(id(m))

m+=300

print(id(m))

print(m)

text(a)

print(a)

结果如下:

2395430277576

2395430277576

2395430277576

[10, 20, 30]

140725538500080

140725538500080

2395460236880

400

100

四,浅拷贝与深拷贝

浅拷贝:只拷引用,不拷内容。只不过指向同一地址。

深拷贝:全部拷贝(拷贝引用的引用)

代码如下:

#浅拷贝

import copy

a=[10,20,[5,6]]

b=copy.copy(a)

print(a)

print(id(a))

print(b)

print(id(b))

b.append(30)

b[1]=2

b[2].append(7)

print(a)

print(b)

print(id(a[1]))

print(id(b[1]))

print()

#深拷贝

import copy

a=[10,20,[5,6]]

b=copy.deepcopy(a)

print(a)

print(id(a))

print(b)

print(id(b))

b.append(30)

b[2].append(7)

print(a)

print(b)

print()

结果如下:

[10, 20, [5, 6]]

2707173823368

[10, 20, [5, 6]]

2707174317896

[10, 20, [5, 6, 7]]

[10, 2, [5, 6, 7], 30]

140725538497520

140725538496944

[10, 20, [5, 6]]

2430962695432

[10, 20, [5, 6]]

2433061442504

[10, 20, [5, 6]]

[10, 20, [5, 6, 7], 30]

由代码可以看出:深拷贝两个对象完全不相关。在浅拷贝中,b[1]=2,这条代码,意思是:本来a【1】,b[1],指向同一个对象,但是b修改了b【1】所以,a与b不同,但改变b【2】【1】就改变的是同一个目标。

注意以下程序:

a=(10,20,[5,6])

print(id(a))

def fun(m):

print(id(m))

#m[0]=30 #会报错

m[2][1]=300

print(id(m))

fun(a)

print(a)

结果为:

2707205833256

2707205833256

2707205833256

(10, 20, [5, 300])

在传递不可变对象时,如果不可变对象里包含可变对象,则在函数内修改这个可变对像,原对象也会改变。

五,参数的类型

1,位置参数

2,默认参数(默认参数一定要在普通参数后)

3,命名参数

4,可变参数(一个*为元组,两个

为字典)

5,强制命名参数(带

的变量后加普通变量要用)

代码如下:

#位置参数与命名参数

def fun(a,b,c,d):

print('{0}-{1}-{2}-{3}'.format(a,b,c,d))

fun(1,2,3,4) #位置参数

fun(d=1,c=2,b=3,a=4) #命名参数

#默认值参数

def fun1(a,b,c=20,d=30):

print('{0}-{1}-{2}-{3}'.format(a,b,c,d))

fun1(1,2)

fun1(1,2,3)

#可变参数

def fun2(a,b,*c,**d):

print('{0}-{1}-{2}-{3}'.format(a,b,c,d))

fun2(1,2,3,4,5,name='lhy',age=20)

结果如下:

1-2-3-4

4-3-2-1

1-2-20-30

1-2-3-30

1-2-(3, 4, 5)-{'name': 'lhy', 'age': 20}

六,lambda表达式声明匿名函数

lambda 变量:表达式

f=lambda a,b:print('***')

print(f)

print(f(1,2))

def test(a,b):

print('**')

return a+b

g=[lambda a,b:a*b ,test]

print(g[0](5,6),g[1](1,2))

结果如下:

at 0x00000206FB3D6048>

***

None

**

30 3

注意,()代表引用,列表存储函数对象的用法

七,eval()函数

作用如下:

# eval

a='print(\'abcde\')'

eval(a)

d=10

e=20

f=eval('d+e')

print(f)

dict1=dict(d=100,e=200)

print(eval('d+e'))

print(eval('d+e',dict1))

结果如下:

abcde

30

30

300

八,递归函数

自己调用自己,应该包括终止条件与递归步骤

def fun1(n):

print('第{0}次打印'.format(n))

if n==0:

print('over')

else:

fun1(n-1)

print('*'*(n+1))

fun1(4)

结果:

第4次打印

第3次打印

第2次打印

第1次打印

第0次打印

over

*

**

***

****

*****

这里要注意,调用后的打印顺序是从0-4

练习:使用递归算法计算阶乘

#用递归实现阶乘算法

def fun(n):

if n==1:

return 1

else:

return n*fun(n-1)

x=int(input("请输入计算的数字:"))

result=fun(x)

print(result)

结果为:

请输入计算的数字:5

120

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值