Python学习tips

来源:互联网 发布:java获取本地路径 编辑:程序博客网 时间:2024/06/11 02:52

  最近毕设要做机器学习相关,考虑到Python这门语言在web里也经常用,后面也会接触大数据,所以借此机会将Python完完整整地过一遍,这篇文章主要记录一下自己在看书和官方文档时对一些需要注意的东西的理解,学习阶段主要参考书为《Python基础教程(第2版)》、《Python核心编程(第3版)》以及官方提供的“Python 2.7.12 documentation”(因为我以前下的是2.7.12版本Python),学习中会不断更新。


1. 字典的copy()方法

  copy()方法返回一个具有相同键值对的新字典,但是实现的是浅复制(shallow copy),也就是说值本身是相同的(is级别的相同),而不是副本。

In [1]: x = {'username': 'admin', 'machine': ['yyy', 'baz']}In [2]: y = x.copy()In [3]: z = {'username': 'admin', 'machine': ['yyy', 'baz']}In [4]: x['machine'] is y['machine']Out[4]: TrueIn [5]: x['machine'] is z['machine']Out[5]: FalseIn [6]: x['machine'] == z['machine']Out[6]: TrueIn [7]: y['machine'].remove('yyy')In [8]: xOut[8]: {'machine': ['baz'], 'username': 'admin'}In [9]: zOut[9]: {'machine': ['yyy', 'baz'], 'username': 'admin'}In [10]: del y['machine']In [11]: yOut[11]: {'username': 'admin'}In [12]: xOut[12]: {'machine': ['baz'], 'username': 'admin'}

  这里,copy()只满足相等性,不满足同一性,x[‘machine’] is y[‘machine’]返回True,而x[‘machine’] is z[‘machine’]返回False,也就是说y对键machine所映射的值做任何更改都会影响x[‘machine’],因为本质上x、y这两个对象的’machine’指向了同一块内存区域(即同一个对象)。
  具体分析原因:这里machine键映射的是list的地址,copy()复制的是这种映射关系,也就是说y的键是新键(删除y的machine项不影响x),但映射的仍然是x创建的list对象。
  避免映射关系为地址这个问题的方法是使用深复制(deep copy),此时键所对应的值都是一个新的对象,互不干扰(下面的代码所示),函数为copy模块里的deepcopy()。

In [15]: from copy import deepcopyIn [16]: d = deepcopy(x)In [17]: d['machine'] is x['machine']Out[17]: FalseIn [18]: x['machine'][0] = 'new'In [19]: xOut[19]: {'machine': ['new'], 'username': 'admin'}In [20]: dOut[20]: {'machine': ['baz'], 'username': 'admin'}

2. None

  这类数据只有一类类型,即NoneType类型,NoneType类型只有一个值——就是None。某些场景下逻辑上需要一个值,但这个值物理上并不存在,就可以赋值为None,比如说函数逻辑上需要返回值,一个没有显式定义返回值的函数不符合逻辑,为了符合函数的定义,这个函数被调用时就返回了None值,None的真值为False。


3. Python函数的参数的区分

  Python作为一门脚本语言,其函数的参数在定义函数和调用函数时变化很多,关于各类参数的叫法,网上和书本上的资料很杂乱,我这里结合“Python 2.7.12 documentation”Glossary里关于parameter和argument的解释给出我自己的理解。
  由于parameter和argument都被翻译做参数,所以有些中文命名就混淆了,实际上,parameter指函数定义里的参数,也就是形参;而argument指函数调用时传给函数的实际参数,也就是实参

关于argument,文档里提到有两种实参:

  • 关键字参数(keyword argument,翻译成实参会好一点?):也就是调用函数时,采用键值对方式传值的参数,这种传递参数的方式叫做关键字参数,如下所示;
# complex定义原型class complex([real[, imag]]) 
complex(real=3, imag=5)complex(**{'real': 3, 'imag': 5})#使用**号将字典解包裹,**{'real': 3, 'imag': 5}等价于real=3, imag=5
  • 位置参数(positional argument,同上翻译成位置实参会清晰一些):除开键值对方式传值的参数,都叫位置参数,如下所示。
complex(3, 5)complex(*(3, 5))#使用*号将元组解包裹,*(3, 5)等价于3, 5

  需要注意的是字典形式的传值属于关键字参数,而以元组传值的方式属于位置参数,这两种形式的传值方式又叫做解包裹(unpacking)参数。所以关键字参数或位置参数都是属于函数调用时的定义,并且,位置参数必须出现在关键字参数前面,也就是说一旦采用键值对方式传值后,该键值对后面出现了非键值对,那么调用失败!

关于parameter,文档里提到了四种形参:

  • 位置或关键字(positional-or-keyword):定义时混用位置和关键字,如下所示;
 def func(foo, bar=None): ...
  • 只有位置(positional-only):定义时只有关键字;
  • 可变数目位置(var-positional):定义函数时,参数的个数可变,但均不使用关键字形式定义形参,如下args形参;
def func(*args, **kwargs): ...
  • 可变数目关键字(var-keyword):定义函数时,参数的个数可变,但是为关键字形式定义形参,如上的kwargs形参。

  官方文档里对形参的划分不是很友好,我根据网上出现的各种名词加以自己的理解做了一个总结:

形参类型 例子 备注 必选参数 def func(x) x在调用函数时必须按位置或以关键字参数指定,x是必选参数 默认参数 def default_func(key=value) 定义函数时参数key使用了键值对指定默认值,key就是默认参数 包裹(packing)位置参数 def packing_positional_func(*args) 定义函数时使用了*,此时将传入的零个或多个值放置在一个元组args内,args就是包裹位置参数 包裹(packing)关键字参数 def packing_keyword_func(**kwargs) 定义函数时使用了**,此时将传入的零个或多个键值对放置在一个字典kwargs内,kwargs就是包裹关键字参数

  注意:
  (1)定义函数时,必须按照必选参数、默认参数、包裹位置参数和包裹关键字参数的顺序定义形参列表;
  (2)包裹位置参数和包裹关键字参数可合称为可变参数或收集参数;
  (3)必选参数依然可以使用关键字参数形式传参,而默认参数也可以使用位置参数形式传参;
  (4)如果一个函数在定义里同时使用了默认参数及包裹位置参数,那么默认参数只能采用位置参数形式传值,这是由于位置参数必须出现在关键字参数前面,所以默认参数就不能使用关键字参数传值了,如下所示:

def func(param1='param1', *args):    print param1    print argsfunc(12, 1, 2, 3)# 12# (1, 2, 3)# func(param1=12, 1, 2, 3)# SyntaxError: non-keyword arg after keyword arg

4. Python2和Python3共存

  有时候需要同时使用Python2和Python3,在windows下同时安装Python2和3时,怎么启动两个编译器,pip又怎么区分是个问题,我在网上看了一些资料后,这里做一个小结。
  在windows上安装好两版的Python后,进入cmd,此时Python3会覆盖掉Python2的设置,也就是说,使用Python进入Python界面或者直接使用pip install命令都是在Python3下工作,这是由于安装Python3,安装器会自动在C盘的Windows文件夹下生成一个py.exe和pyw.exe的文件,这两个文件可以区分Python2和Python3,但默认是Python3,启动Python2,就需要使用命令”py -2”了。

动作 Python2 Python3 cmd启动编译器 py -2 py -3或python
pip安装包 pip2 install package-name
py -2 -m pip install package-name pip3 install package-name
pip install package-name
py -3 -m pip install package-name
脚本执行 py -2 script-name py -3 script-name
python script-name
py script-name

  注意:脚本执行还可以通过在脚本里加入一行注释也可实现区分,如果由python2解释运行,那么可以在脚本的第一行(一定要在脚本首行,即出现在”# -*- coding: utf-8 -*-“前面)加入

#!python2

如果是python3,那么在首行加入

#!python3

之后,运行脚本时,使用py script-name即可按希望的解释器运行,此时如果指定python2,则不能用python script-name运行脚本,如果是python3,则可以使用python script-name。