关闭

几个python语法知识(一)

标签: python
227人阅读 评论(0) 收藏 举报
分类:

最近看了廖雪峰老师的博客中关于python的内容,感觉收获良多。

廖雪峰的博客:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000


1、关于.py文件的编码问题

这个问题困扰我很久,一直疑惑于.py文件中的中文字符串常量的编码问题。

我们经常在程序的第一行写入:

# -*- coding: utf-8 -*-

以为这样,整个文件就是utf-8的编码了。其实并不是,在我的实践中,我发现该文件下的中文字符串常量,并不是utf-8编码的。我尝试使用以下语句:

'蛋糕'.decode('GBK').encode('utf8')
这样才能得到utf-8下的中文字符串。这是为什么呢?

原因在于,在Windows系统环境下,一个文件的默认编码为ANSI编码,其中的中文字符默认编码为GBK。

如果我们在Notepad++中,将.py文件格式改变为UTF-8 without BOM,这样才可以保证文件中的中文字符串为utf-8编码。

而第一行注释又有什么意义呢?

该注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

看个例子:

# -*- coding:utf-8 -*-
a=['中文']
print a
同样的文件,在记事本编辑环境下,输出为:

['\xd6\xd0\xce\xc4']
可以验证编码为GBK。

而在notepad下以UTF-8 without BOM编辑,输出为:

['\xe4\xb8\xad\xe6\x96\x87']
为utf-8编码。

如果.py文件本身使用UTF-8编码,并且也申明了# -*- coding: utf-8 -*-,打开命令提示符测试就可以正常显示中文。


2、关于元组tuple

除list外,另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改。

获取元素可以使用下标,但是无法修改,没有append、insert方法。

如果要定义一个只有1个元素的tuple,记得在后面加逗号。


3、关于dict

dict使用的key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key。


4、关于set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错。


5、不可变对象

对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。


6、返回多个值

import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

多个值之间使用逗号分隔,这样返回的是一个元组tuple。


7、默认参数

关于默认参数,有个大坑例子:

def add_end(L=[]):
    L.append('END')
    return L

使用默认参数调用时:

>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

原因解释如下:


Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

所以,定义默认参数要牢记一点:默认参数必须指向不变对象!


8、可变参数

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
调用:

>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84


9、关键字参数

def person(name, age, **kw):
    print 'name:', name, 'age:', age, 'other:', kw

调用:

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}


10、列表生成式

好像只能用来生成列表?

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

11、生成器

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>

定义generator的另一种方法,如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18055次
    • 积分:1101
    • 等级:
    • 排名:千里之外
    • 原创:96篇
    • 转载:11篇
    • 译文:0篇
    • 评论:4条
    文章分类
    最新评论