Python基础学习笔记
学习廖雪峰的Python 2.7教程的笔记,关注Javaer觉得比较不同和值得记录的地方。
基础
1 | print "hello","world" #中间连空格 |
Python是动态语言(变量本身类型不固定的语言),常量一般全部大写。
编码(涨姿势)
美国 ASCII、中国 GB2312 => 统一 Unicode => 可变长 UTF-8(相当于UTF-8包含了ASCII)
内存中统一使用Unicode编码。保存到硬盘 或者 传输的时候,就转换为UTF-8编码。1
2
3
4
5
6ord('A')
chr(65) #字符和ASCII转换
u'中' #Unicode字符串
u'中'.encode('utf-8') #Unicode转换为UTF-8
u'中'.encode('gb2312') #Unicode转换为GB2312
'\xe4\xb8\xad'.decode('utf-8') #UTF-8转换为Unicode
Python 2.x版本虽然支持Unicode,但在语法上有’xxx’和u’xxx’两种字符串表示方式。
在Python 3.x版本中,把’xxx’和u’xxx’统一成Unicode编码,即写不写前缀u都是一样的,而以字节形式表示的字符串则必须加上b前缀:b’xxx’。
因此.py
的文件头必须加上:1
2
# -*- coding: utf-8 -*-
第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
列表 list
1 | list=[1,'二',True,[0,9]] #各种类型都可以 |
元组 tuple
相当于一旦初始化就不能修改的list1
2tuple=(1,'二',True,(0,9),[0,9]) #存在数学括号的歧义性
x,y=(1,'二')
字典 dict
就是Java中的map般的存在,键值对1
2
3dict = {'Zhang': 95, 'Li': 75, 123: 85}
dict['Wang']=88
dict.pop('Li')
key的对象就不能变,如字符串、整数等
避免key不存在的错误:一是通过in
判断key是否存在,二是通过dict提供的get(key)
方法
set
这Java中也有,不重复的key,且没有value1
2
3s=set([1,1,2,2,3,3])
s.add(1)
s.remove(1)
条件判断
1 | if <条件判断1>: |
else if => elif
{ } => 缩进
还有都要:
符号
循环
1 | str='helloworld' |
pass
是空语句,是为了保持程序结构的完整性。
函数
参数顺序为必选参数 > 默认参数 > 可变参数 > 关键字参数
默认参数,必须指向不变对象,不能是List。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21def my_abs(x=0):
if not isinstance(x, (int, float)): # 类型检查
raise TypeError('bad operand type')
if x >= 0:
return x,'正'
else:
return -x,'负' #返回tuple
```
可变参数,在函数调用时自动组装为一个tuple。
```python
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
1, 2) calc(
1, 2, 3] nums = [
calc(*nums)
关键字参数,允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。1
2
3
4
5
6
7
8
9
10def func(a, b, c=0, *args, **kw):
print 'a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw
1, 2, 3, 'a', 'b', x=99) func(
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
1, 2, 3, 4) args = (
'x': 99} kw = {
#奇了个葩 func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'x': 99}
个人对原文“对于任意函数,都可以通过类似func(args, **kw)的形式调用它,无论它的参数是如何定义的”的修改意见:定义时含有可变参数和关键字参数的函数,才可以通过类似func(args, **kw)的形式调用它。如果1
2def func(a,b,c=0):
# 略
并不能通过func(args, **kw)调用。
实际上,`func(args, **kw)`是函数的通用形式。
切片
可对list、tuple、字符串进行切片。1
2
3
4list=[1,'二',True,[0,9]]
list[::2] #步长为2
range(100)[:10:2]
'abcdefg'[:3]
迭代
只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代。1
2from collections import Iterable
isinstance('abc', Iterable) # 判断str是否可迭代
1 | for x, y in [(1, 1), (2, 4), (3, 9)]: |
列表生成式
即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。1
2
3L=[str(k)+'='+str(v) for k,v in {"Zhang":95,123:66}.iteritems()] #注意不要声明和内置方法同名的变量或方法,比如str="123",就会导致str(123)不能用
L=[x*y for x in range(1,4) for y in range(1,5) if x+y>5] #列表生成式
L=[x*y if x+y>5 else 0 for x in range(1,4) for y in range(1,5)] #列表生成式还可带条件
1 | L =['Hello', 'World', 18, 'Apple', None] #将是str类型转换为小写,且保留非str |
补充:留言有关于列表生成式和条件表达式的讨论,个人观点
列表生成式1
2
3
4comprehension ::= expression comp_for
comp_for ::= "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" expression_nocond [comp_iter]
条件表达式1
2
3conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
expression_nocond ::= or_test | lambda_expr_nocond
注意到
- 条件表达式 | lambda表达式 + for 是列表生成式的一种形式
- 条件表达式没有for
- 列表生成式中的
comp_if::= "if" expression_nocond [comp_iter]
有for,但并不是条件表达式
所以方法一中的s.lower() if isinstance(s,str) else s
是条件表达式,这是列表生成器。而方法二中的s.lower() for s in L if isinstance(s,str) else s
不是条件表达式,if isinstance(s,str) else s for s in L
也不是条件表达式而符合列表生成器的comp_if ::= "if" expression_nocond [comp_iter]
,所以也是列表生成器。
生成器
一边循环一边计算的机制,节省内存。可用()
和关键字yield
声明。1
2g = (x * x for x in range(10))
g.next() #也可迭代
1 | def fib(max): |
在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
函数式编程
一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量(内部)。Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
变量可以指向函数f=str()
,函数名也是变量str=123
。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。高阶函数可以接受函数作为参数外,还可以把函数作为结果值返回。
- 传入函数
接受一个函数和一个序列的函数包括1
2
3
4map(f, [x1, x2, x3, x4]) #相当于[f(x1),f(x2),f(x3),f(x4)]
reduce(f, [x1, x2, x3, x4]) #相当于f(f(f(x1,x2),x3),x4)
filter(f, [x1, x2, x3, x4]) #如果f(x1)为True,则保留,否则丢弃
sorted([x1, x2, x3, x4],f) #可根据f返回的1、0、-1排序
以实现类型转换函数int()
为例:1
2
3
4def str2int(s):
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
return reduce(lambda x,y: x*10+y, map(char2num, s))
函数内可以定义函数,内部函数可以引用外部函数的参数和局部变量。
- 返回函数
相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。每次调用都会返回一个新的函数。
p.s. 闭包的知识略微复杂,为此专门另写了一篇博客《闭包的概念、例子和作用》
p.p.s 由于Python2的bug,廖博客中的代码实际需要修改,可见python中的闭包一文,详细的探究过程来自Python的闭包研究一文。