首页 > 代码库 > 【Python】 零碎知识积累 III

【Python】 零碎知识积累 III

零碎积累 III

■  函数的参数默认值在函数定义时确定并保存在内存中,调用函数时不会在内存中新开辟一块空间然后用参数默认值重新赋值,而是单纯地引用这个参数原来的地址。这就带来了一个坑,那就是当你在函数体中对默认参数做一些改变的时候,若参数默认值是int,str这种不可变类型,那么还好,因为默认参数在内存中并没改变,只是参数指向另一块空间;但若是list这种可变类型,当你对默认参数做改变的时候,将会直接影响这个参数在内存中实际的值,这也就影响了下次调用这个函数时参数的默认值。比如:

def foo(para=1):
    para += 1
    print para
>>>foo()
2
>>>foo()        #第二次调用结果不变
2

def foo(para=[1])
    para.append(1)
    print para
>>>foo()
[1,1]
>>>foo()    #第二次调用会显示出第一次调用过程中的一些影响,因为默认参数值是个可变型数据结构,对其所做的改变会真实反应到内存中去
[1,1,1]

 

■  获取当前脚本的绝对路径

  os.path.abspath(__file__)

  __file__这个魔法变量的意思是指代文件本身

 

■  判断某个类是否有某个属性(变量或者方法)用hasattr函数。这个函数有两个参数,第一个是一个类的实例,第二个是个字符串来指出想要检查的属性名。比如:

  令s = "hello". s就是个字符串了。然后hasattr(s,"strip")就是判断s这个实例有没有名为strip的属性。事实上字符串有strip这个方法,所以返回True

 

■  第三方模块charset可以检测字符串的编码格式,安装用pip install charset

  使用charset.detect("一个字符串")

  需要注意的是直接输入一个中文字串似乎只是查看这个文件默认的编码格式而已,因为中文被存进内存的时候会被python用默认编码格式处理一下。

 

■  想要查看某个模块的源码之类的情况,需要知道这个模块的路径。可以在python中import这个模块之后,在pythonshell中直接键入模块名,就会显示路径了。

 

■  list类增加成员有很多种方法,比如:

  [1].append(2)  //前两种方法都是直接对内存中list本身的内容做修改。

  [1].extend([2])

  [1]+[2]  //这种方法其实是要在内存中建立一个新的list对象来盛放两个老list合起来的内容

  从运行速度的效果来看,第三种是最慢的因为要建立一个新对象

 

■  关于可变&不可变对象 数据在内存中的形态

  其实这点内容应该是学python时最早就应该懂的,我当时学的时候没在意太多,现在还要回过头来再仔细看一遍。。

  在python之中,一切皆对象。意思是说,一个变量或者函数之类的,只是引用了内存中存在的一些实在的数据而并不被直接存进内存。这就引出了一个问题,当我对变量的值进行一些改变时,是让变量换一个引用对象呢还是说直接在当前引用对象上修改呢?另外,当我增加一个变量,值和现在的变量一样,它引用的是同一片内存空间呢还是说引用另一片内存空间只是内容一样呢?这个区别就是不可变和可变类型的区别。

  对于int,str,tuple这种不可变类型。相同的值的变量引用的是同一个对象,改变变量的值相当于改变这个变量的引用,使之指向另一个对象了:

>>>x = 1
>>>y = 1
>>>id(x) == id(y)
True
>>>x += 1
>>>id(x) == id(y)
False

  对于list,dict这种可变类型。相同的值的变量引用的也是不同的对象。改变变量的值相当于直接在内存中的对象上做改变但变量的引用关系不变:

>>>x=[1]
>>>y=[1]
>>>id(x) == id(y)
False
>>>oldXID = id(x)
>>>x.append(2)
>>>id(x) == oldXID
True

   总的来看,不可变类型的好处是多个等值变量可以只引用一个对象,节省内存。但变量值变化较多的情况就要创建出各种各样的对象来,就不是很好了。

  顺便一提,在判断相等时的is和==也是这个差别。is判断的是是不是引用对象一致。而==判断的只是引用对象的值是不是一致。

 

【Python】 零碎知识积累 III