Python 常用函数和内存分配

Python的函数参数传递

所有的变量都可以理解是内存中一个对象的“引用”,对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。可更改对象在引用发生变化时候随着变化,不可更改对象的引用发生改变不影响原对象值。

#不可更改的对象
a=1
def fun(a):
    a=2
fun(a)
print(a)  #1
#可更改对象
a=[]
def fun(a):
    a.append(1)
fun(a)
print(a) #[1]

2.python 中内存管理

1)垃圾回收

Python 不像C++,Java等语言,可以不事前声明变量而对变量赋值,对Python语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称Python语言为动态类型的原因。(内存地址的分配是在运行时自动判断变量类型并对变量进行赋值)
①当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
②当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。

2)引用计数

Python采用了类似Windows内核对象一样的方式来对内存进行管理。每一个对象,都维护这一个对指向该对对象的引用的计数。
引用计数增加的情况:
①一个对象被创建 a = 223
②对象被引用 b=a
③对象被作为参数 func(a)
②将其放入一个容器中(如列表、元组或字典) list=[a]

引用计数减少的情况:
①使用del语句对对象别名显示的销毁 del a
②被重新赋值 a=224
③对象离开作用域
④对象所在容器被销毁,或则从容器中删除对象

3)内存池机制

Python的内存机制以金字塔行,-1,-2层主要有操作系统进行操作,
第0层是C中的malloc,free等内存分配和释放函数进行操作;
第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;
第3层是最上层,也就是我们对Python对象的直接操作;
①Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
②Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。

经由内存池登记的内存到最后还是会回收到内存池,并不会调用 C 的 free 释放掉.以便下次使用.对于简单的Python对象,例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝),也就是说当将另一个变量B赋值给变量A时,虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同。而对于像字典(dict),列表(List)等,改变一个就会引起另一个的改变,也称之为浅拷贝。

3.Python lambda函数

lambda的一般形式是关键字lambda,之后是一个或多个参数(与一个def头部内用括号括起来的参数列表及其相似),紧跟的是一个冒号,之后是一个表达式:
lambda argument1,… argumentN:expression using argument

由lambda表达式所返回的函数对象与由def创建并复制后的函数对象工作起来是完全一样的,对简单函数的简洁表示。但是lambda由一些不同之处让其在扮演特定的角色时很有用。
case1:

#python
fun = [(lambda n : i + n) for i in range(10)]  
print(fun[3](4)) 
print(fun[4](4)) 

输出结果13,13,并非期望的7,8

解析:fun为一个函数数组,i为全局变量,即为9。fun3指调用fun中第三个函数,n赋值为3,所以结果为13。同理可得fun4值为13。
case2:

#如下修改则可以得到7,8
fun = [(lambda n,i = i : i + n) for i in range(10)]  
print(fun[3](4)) 
print(fun[4](4))

case3:如果使用过filter/map/reduce这几个函数,就会知道lambda表达式真的在匿名函数的写法上非常省时省力。

print filter(lambda x : x % 2 == 0, range(10))  
print map(lambda x, y : x * y, range(1,4), range(1,4))  
print reduce(lambda x, y : x + y, range(101)) 

输出结果:
[0, 2, 4, 6, 8]
[1, 4, 9]
5050

pass语句作用

pass语句不会执行任何操作,一般作为占位符或者创建占位程序

if true:
    pass #do nothing
else:
    #do something

zip

zip函数的原型为:zip([iterable, …])
参数iterable为可迭代的对象,并且可以有多个参数。该函数返回一个以元组为元素的列表,其中第 i 个元组包含每个参数序列的第 i 个元素。返回的列表长度被截断为最短的参数序列的长度。只有一个序列参数时,它返回一个1元组的列表。没有参数时,它返回一个空的列表。
case1:

import numpy as np
a=[1,2,3,4,5]
b=(1,2,3,4,5)
c=np.arange(5)
d="zhang"
zz=zip(a,b,c,d)
print(zz)

输出:
[(1, 1, 0, ‘z’), (2, 2, 1, ‘h’), (3, 3, 2, ‘a’), (4, 4, 3, ‘n’), (5, 5, 4, ‘g’)]

zip() 和 * 操作符一起操作可以用来 unzip 一个列表,看下面的代码:(其实就是前面的反向操作,把一个列表拆成几个)
case2:

import numpy as np
a=[1,2,3]
b=[4,5,6]
c=[7,8,9]
zz=zip(a,b,c)
print(zz)
输出:[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

x,y,z=zip(*zz)
print(x)
print(y)
print(z)

输出:
(1, 2, 3)
(4, 5, 6)
(7, 8, 9)

join

一、函数说明
1、join()函数

语法: ‘sep’.join(seq)

参数说明
sep:分隔符。可以为空
seq:要连接的元素序列、字符串、元组、字典
上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串

返回值:返回一个以分隔符sep连接各个元素后生成的字符串

>>> seq1 = ['hello','good','boy','doiido']

>>> print ' '.join(seq1)

hello good boy doiido

>>> print ':'.join(seq1)

hello:good:boy:doiido

2、os.path.join()函数

语法: os.path.join(path1[,path2[,……]])

返回值:将多个路径组合后返回

注:第一个绝对路径之前的参数将被忽略

>>> import os

>>> os.path.join('/hello/','good/boy/','doiido')

'/hello/good/boy/doiido'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值