python基础语法

 

动机

曾学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的迭代器有两种,IterableIterator.

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()