动机
曾学python于廖雪峰,合力建django站.
久不用,全忘.
归峰复学,恐再忘,记于此,易寻.
且记基础.
目录结构仿廖雪峰,目前非python项目,仅记录至基础语法 函数编程 面向对象编程,可支持偶尔调库即可.
python使用缩进代替{}做层次设计,把编辑器的tab设为4个空格会避免很多麻烦.
语法记录
基础语法
输入输出
基本同c 略有不同 一干二净
print('hello,cat', "!",100+200) # ''和""都可 ,会转为空格,任意原始数据类型都可
print('%d %%' % 7) # %需用%转义,\需用\转义 %d %s %f %x 16进制
a = 1
a = 1.1
a = '1'# 动态语言 无类型限制
name = input("please input your name") # 可以没有参数
print('中文'.encode('utf-8'))
print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))#python3默认使用utf-8
数组
python内置list和tuple作为数组类型,list可变,tuple不可变,数组内各元素类型可以不同,可以是list/tuple.
cats = ['cat', 'another_cat', 'the_third_cat'] # []表示list,()表示tuple list和tuple可以直接输出,python内置了输出格式
print(len(cats), cats[0], cats[1], cats[2], cats[-1], cats[-2], cats[-3]) # 3和-4会越界
cats.append('the_fourth_cat') #添加在结尾
cats.insert(1,'insert_cat') #插入到1
cats.pop() #移除结尾
cats.pop(1) #移除某个元素
cats[2] = 'new_another_cat' #修改某元素
a, b, c = [1, 2, 3] #批量赋值 函数多值返回的实现
条件判断和循环
根据什么/谁说过,顺序 条件判断 循环可以完成所有流程,并且拥有较goto更好的可读性.
age = input('age:')
age = int(age)
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid') #无力注释
cats = ['cat', 'another cat', 'thethirdcat']
for cat in cats:
print(cat) #c++11也支持类似语法了 for (auto i : v)
for i in range(5);
sum += i
list(range(5))# range返回不是list,可以转list
n = 1
while n <= 100:
if n > 10: # 当n = 11时,条件满足,执行break语句
break # break语句会结束当前循环
if n % 2 == 0: # 如果n是偶数,执行continue语句
continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
print(n)
n = n + 1
print('END')
字典
dict和set,c++的hash_map,默认无需,dict似乎有支持有序的倾向.
内存换速度.
d = {'Michael':95,'Bob':75,'Tracy':85} #key必须是不可变对象/实参,不能是指针/形参 key value类型无限制
print(d['Michael']) #通过key访问value 可修改
d.get('Michael') #不存在返回None
d.get('Michael',-1) #不存在返回-1
print('Michael' in d) # 判断是否存在
d.pop('Michael') # 删除
s = set([1,2,3]) #只有key 没有value,list输入 自动去重
s.add(4)
s.remove(4)
s1 = set([1,3,4])
s2 = set([2,3,4])
print(s1 & s2) # 2 3
print(s1 | s2) # 1 2 3 4
函数
大同小异,语法格式略不同
函数的定义
可以返回多个参数,自动转为tuple返回
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')#判断类型
if x >= 0:
return x
else:
return -x
函数的参数
有五种参数,必选参数 默认参数 可变参数 关键字参数 命名关键字参数.
可以同时/单独使用,类型顺序不可变.
# 默认参数
def enroll(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
enroll('cat','boy',city = 'Beijing')
enroll('cat','boy',12)
# 必选参数和可变参数
from functools import reduce
def p(x, y):
return x * y
def product(func, *args):
return reduce(func, args)
print(product(p, 1, 2, 3))
l = [1, 2, 3]
print(product(p, *l))#可以把list和tuple加*作为可变参数传入
# 关键字参数
def person(name, age, **k):
print("name: ", name, "age: ", age, k)
person('cat', 1, cute='cute')
extra = {'cute': 'cute', 'no-cute': 'no-cute'}
person('cat', 1, **extra)
# 命名关键字参数
def person(name, age, *, city, job='cat'):
print(name, age, city, job)
person('cat', 1, city = 'beijing')
# *参数或可变参数后的参数为命名关键字参数.
def person(name, age, *args, city, job='cat'):
print(name, age, args, city, job)
person('cat', 1, 1, 2, 3, city='beijing')
递归
并没有什么特殊
def fbnq(n):
if(n==1):
return 1;
if(n==2):
return 2;
return fbnq(n-1)+fbnq(n-2)
python的高级特性
python用简单的接口提供原本需要繁琐代码的操作,易读易写.如果会的话.
切片
取一个list tuple的部分元素.string可以看做list.
L = range(100)
r = []
n = 3
for i in range(n):
r.append(L[i])
r1 = L[:] #完全复制
r1 = L[0:10] # 取L中索引为0的元素到索引为10-1的元素,共取10-0个元素
r1 = L[:10] # 索引为0可以省略
r1 = L[-2:-1] #返回倒数第二个
r1 = L[-1:] # 返回最后一个
r1 = L[:10:2] #前10个 每两个取一个 从第0个开始
迭代
for in型花式循环
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
print(key, d[key]) # 顺序不定
for v in d.values(): # values 返回类似list
print(v)
for k, v in d.items():
print(k, v)
for ch in 'ABC':
print(ch)
l = [11, 12, 13]
for i, value in enumerate(l):
print(i, value) # enumerate把list转换为key-value的dict
for x, y in [(1, 1), [2, 2]]: #list和tuple转对应元素数量的变量
print(x, y)
列表生成式
像切片一样的技巧,用于生成list.
list(range(1,11)) #生成1-10的数组
[x*x for x in range(1,11)]
[x*x for x in range(1,11) if x % 2 == 0]
[m + n for m in 'ABC' for n in 'XYZ']
import os
print([d for d in os.listdir('.')]) # 指定目录文件列表
d = {'x': 'A', 'y': 'B', 'z': 'C'}
print([k + '=' + v for k, v in d.items()])
L = ['Hello', 'World', 'IBM', 'Apple']
print([s.lower() for s in L]) # 全部转小写 没有做类型检查
生成器
随循环生成列表内容,节约空间.
一种方式是列表生成器的[]换(),一种方式是对函数使用yield.
效果基本等价于 直接把for循环逻辑和yield前后结合
L = (x * x for x in range(10))
for n in L:
print(n)
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n += 1
f = fib(6)
for b in f://fib每次执行到yield
print(b)
迭代器
python的迭代器有两种,Iterable和Iterator.
Iterable是指可以直接作用于for循环的对象,可迭代对象.
Iterator是指可以作用于for循环,也可以被next()函数调用并不断返回下一个值的对象,迭代器.
这两个词实在找不到靠谱的翻译…
Iterable都是Iterator,两者都可以使用isinstance([],Iterable)判断.
函数式编程
函数亦是变量,可赋给新变量,可改为其他类型
匿名函数
用输出表达式来表示一个单参数函数,不需函数名,完全等价于函数.
print(list(map(lambda x: x * x, [1, 2, 3])))
f = lambda x:x*x
# 等价于
def f(x):
return x * x
f = lambda x, y: x * y
# 等价于
def f(x, y):
return x * y
高阶函数
一个函数作为另一个函数的传入或返回
def f(a):
return a * a
def ff(a, b, f1):
return f1(a) + f1(b)
print(ff(1, 2, f)) # 5
map和reduce
map接受func和可迭代 返回对所有元素依次func后的可迭代对象 reduce接受func和可迭代 返回按顺序依次func(上一次结果,元素)的结果 map(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)
from functools import reduce
DIGITS = {
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9
}
def num2int(x, y):
return x * 10 + y
def char2num(c):
return DIGITS[c]
def str2int(s):
return reduce(num2int, map(char2num, s))
print(str2int("123"))
filter
类似map和reduce,批量过滤迭代器中的元素.
def isodd():
return lambda x: x % 2
print(list(filter(isodd(), list(range(10)))))#isodd() 返回一个函数对象
# 等价于
def isodd(x):
return x % 2
print(list(filter(isodd, list(range(10)))))
# 生成所有素数
def _odd_iter():
n = 1
while True:
n += 2
yield n
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it) # 每次从_odd_iter获得next后, 完成所有的_not_divisible(n) n = 2, 3, 5 ,7...
yield n
it = filter(_not_divisible(n), it)
for n in primes():
if n > 100:
break
print(n)
sorted
排序,基本同c.
def key_int(a):
return -a
print(sorted([1, 3, 2, 4], key=key_int)) # 默认升序 key可空 python开始不支持cmp
返回函数
函数可以作为一个函数的返回
def lazy_sum(*args):
def sum(): # sum中尽量不要依赖循环变量
ret = 0
for arg in args:
ret += arg
return ret
return sum
print(lazy_sum(1, 2, 3))
print(lazy_sum(1, 2, 3)())
装饰器
装饰器是通过对函数的封装,在调用函数时额外执行一些操作,用来打log等.关闭简单,不影响无log代码
def log(func):
def wrapper(*argc, **argv):
print("call:%s()" % func.__name__, argc, argv)
return func(*argc, **argv)
return wrapper
@log
def sum(a, b):
return a + b
# 等价于 sum = log(sum)
print(sum(*(1, 2), **{}))
偏函数
在函数变量太多的时候,生成一个默认变量更多的新函数名,减少复杂度.
import functools
int2 = functools.partial(int, base=2)
print(int2('1010'))
模块
讲了下自己编写模块 调用模块 安装第三方模块的方法
面向对象编程
同c++.class的每个函数第一个参数必须为self,不传递.
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
def print_age(self):
print('%s: %d' % (self.name, self.age))
cat = Student('cat', 11) # 不支持 Student cat('cat', 11)
cat.print_age()