数据结构
# =========base
print('=================base')
name = 'name'
print('hello,忠翁', name)
print('''line1
line2
line3''')
print('hello %s, %.2f ' % ('zw', 1.22222))
# ==========list
print('=================list')
list_1 = [1, 2, 3]
print(list_1[0], list_1[-1])
# -----基本操作
list_1.append(4)
list_1.insert(1, 11)
print(list_1)
list_1.pop()
print(list_1)
list_1.pop(1)
print(list_1)
# ------不同类型
list_1.append('s1')
list_1.append(['a1', 'a2'])
print(list_1)
# ===========tuple
# tuple和list非常类似,但是tuple一旦初始化就不能修改
print('=================tuple')
tuple_1 = (1, 2)
print(tuple_1[0], tuple_1[-1])
# --tuple的陷阱:
# 1 定义的时候,tuple的元素就必须被确定下来
# 2 只有1个元素时,必须加一个逗号,,来消除歧义;否则只是定义了一个变量
tuple_2 = (1)
print(tuple_2)
tuple_2 = (1,)
print(tuple_2)
# 3 嵌套元素可能可变,其不变指 直接元素的指向不变
tuple_3 = (1, [11, 12], 2)
tuple_3[1][0] = 10
print(tuple_3)
# ===========set
print('=================set')
set_1 = set([1, 1, 2, 2, 3, 3])
print(set_1)
set_1.add(4)
set_1.add(5)
print(set_1)
set_1.remove(1)
# -- set可以做数学意义上的交集、并集等操作
set_2 = set([1, 2, 'a'])
print(set_1 & set_2 )
print(set_1 | set_2)
# =============dic
print('=================dic')
dic_1 = {'k1':1, 'k2':'v2'}
dic_1[3] = 'v3'
dic_1['k4'] = 'v4'
print(dic_1)
print('k1' in dic_1)
print(dic_1.get('k5'))
dic_1.pop('k1')
print(dic_1)
# ===========条件判断
print('=================if else')
age = 20
if age >= 6:
print('teenager 1')
print('teenager 2')
elif age >= 18:
print('adult')
else:
print('kid')
if age:
print('not empty')
# -- 非零数值、非空字符串、非空list等,就判断为True,否则为False
list_empty = []
if list_empty:
print('list not empty')
else:
print('list empty')
# =============循环
print('=================for while')
# -- for x in ...
for item_list_1 in list_1:
print(item_list_1)
sum = 0
for integer in range(101):
sum += integer
print(sum)
# -- while 表达式
sum = 0
n = 99
while n > 0:
sum += n
if sum < 300:
print('sum[%d] < 300 continue' % sum)
continue
if sum > 2000:
print('sum[%d] > 2000 break' % sum)
break
n -= 2
print(sum)
函数
# 函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”
my_abs = abs
print(my_abs(-100))
# -----------定义函数 def
def fun_abs(x):
if x >= 0:
return x
else:
return -x
print(fun_abs(-200))
# ------------空函数 pass
def fun_empty(a):
pass
def fun_empty_block(a):
if a > 10:
print('pass block')
pass
print(fun_empty(11))
print(fun_empty_block(11))
# -- 参数类型检查
def fun_val_param(x):
if not isinstance(x, (int, float)):
raise TypeError("illegal param")
return -x
# -- 返回多个值
def return_multi(x):
return x+1, x+2
a1, a2 = return_multi(1)
print(a1, a2)
# - 其实这只是一种假象,Python函数返回的一个tuple
print(return_multi(1))
# -- 默认参数
# - 1 必选参数在前,默认参数在后
# - 2 把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数
# - 3 定义默认参数要牢记一点:默认参数必须指向不变对象!
def fun_default_param(name, age = 0, city = '北京'):
print('name:', name)
print('age:', age)
print('city:', city)
fun_default_param('a0', 10, '河北')
fun_default_param('a1', 30)
fun_default_param('a2')
# - 参数非顺序指定,需给出名称
fun_default_param(age=100, city='保定', name='老子')
# - 默认参数有个最大的坑:默认参数L的值[],在函数定义时已计算好,
# - 调用,L指向的默认值是共享的!!
def fun_big_hole(l = []):
l.append('end') # - 关键这里把共享的默认参数值改变了
print(l)
return l
list_def_big_hole = [1]
fun_big_hole(list_def_big_hole)
fun_big_hole(list_def_big_hole)
fun_big_hole()
fun_big_hole()
# -- 可变参数:传入的参数的个数是可变的
def calculate(beg , *numbers):
print('beg', beg)
sum = 0
for n in numbers:
sum += n
print('sum:', sum)
return sum
calculate(1, 1, 2, 3)
calculate(1, *[1, 2, 3])
calculate(4, 5)
calculate(*(4, 5))
calculate(1)
# -- 关键字参数
# 可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple
# 而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
person('Michael', 30)
person('Bob', 35, city='Beijing')
person('Adam', 45, gender='M', job='Engineer')
dic_person = {'k1':1, 'k2':'v2'}
person('XiaoMing', 10, **dic_person)
# -- 命名关键字参数
# 如果要限制关键字参数的名字,就可以用命名关键字参数
# 如只接收city和job作为关键字参数
# 和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数
def person_named(name, age, *, city, job):
print(name, age, city, job)
# 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了
def person_var_named(name, age, *args, city, job):
print(name, age, args, city, job)
# 命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错
# 命名关键字参数可以有缺省值, 调用时,可不传入city参数
def person_var_named_default(name, age, *, city='Beijing', job):
print(name, age, city, job)
person_var_named_default('hao', 10, job = 'jobMe')
# -- 参数组合
# 在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。
# 但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def args_compose_1(b, c=0, *args, **kw):
print('b =', b, 'c =', c, 'args =', args, 'kw =', kw)
args_compose_1(1, 2, 3, 4, 5, kw1 = [1, 1], kw2 = 'kw2')
args_compose_1(1, 2, kw1 = [1, 1], kw2 = 'kw2')
def args_compose_2(b, c=0, *, d, **kw):
print('b =', b, 'c =', c, 'd =', d, 'kw =', kw)
args_compose_2(1, 2, d = 'hello', kw1 = [1, 1], kw2 = 'kw2')
args_compose_2(1, 2, a = 'a', d = 'd')
高级特性
from collections import Iterable
# ========== 切片
# -- 开始索引:结束索引(但不包括)
L = [0, 1, 2, 3, 4, 5]
print(L[0:3])
print(L[:3])
print(L[-1:-2])
print(L[-2:-1])
print(L[-2:])
L2 = L[:]
L2[0] = 10
print(L)
print(L2)
# --tuple也是一种list,唯一区别是tuple不可变。
# tuple也可以用切片操作,只是操作的结果仍是tuple
T = (1, 2, 3, 4)
print(T[:2])
# -- 字符串'xxx'也可以看成是一种list, 每个元素就是一个字符。
# 字符串也可以用切片操作,只是操作结果仍是字符串
S = '123456'
print(S[:3])
# ===========迭代 iterable
# 当我们使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行,
# 而我们不太关心该对象究竟是list还是其他数据类型。
D = {'a': 1, 'b': 2, 'c': 3}
for key in D:
print(key)
for value in D.values():
print(value)
for item in D.items():
print('item', item, ' key:', item[0], " v:", item[1])
# - 如何判断一个对象是可迭代对象呢?
# - 方法是通过collections模块的Iterable类型判断
print(isinstance(D, Iterable))
print(isinstance('123', Iterable))
# - 如果要对list实现类似Java那样的下标循环怎么办?
# - Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身
print(enumerate(D))
for i, key in enumerate(D):
print(i, key)
# ==================列表生成式
# -- 生成[1x1, 2x2, 3x3, ..., 10x10]
print( [x * x for x in range(1, 11)])
# -- for循环后面还可以加上if判断
print([x * x for x in range(1, 11) if x % 2 == 0])
# -- 使用两层循环(甚至三层或以上)
print([m + n for m in 'ABC' for n in 'XYZ'])
# -- for循环其实可以同时使用两个甚至多个变量
d = {'x': 'A', 'y': 'B', 'z': 'C' }
print([k+'='+v for k, v in d.items()])
# ===================(数据、逻辑)生成器
# 一边循环一边计算的机制, 生成器内部保存的是逻辑,吐出的是数据/逻辑,有点像发射器
g = (x for x in range(5))
print(g)
print(next(g))
print(next(g))
print('--- in g ')
for n in g:
print(n)
# 斐波拉契数列(Fibonacci) 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
# 斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易
def fibonacci(index, resList):
n = 0
a = 0
b = 1
while n < index:
resList.append(b)
a, b = b, a + b
n += 1
fib_res = []
fibonacci(6, fib_res)
print(fib_res)
# - fibonacci逻辑其实非常类似generator
# - 把 fibonacci 函数 变为 generator, 只需要增加yield b就可以了
# - generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
# 而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,
# 再次执行时从上次返回的yield语句处继续执行。
def fib_generator(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 相当于数据流的源头
a, b = b, a + b
n = n + 1
return 'done'
# - 但是用for循环调用generator时,发现拿不到generator的return语句的返回值。
# 如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中
gen_fib = fib_generator(5)
while True:
try:
print(next(gen_fib))
except StopIteration as e:
print('return value:', e.value)
break
函数式编程
# ===============函数式编程
# - 公式性质:只要输入是确定的,输出就是确定的
# - 函数可做参数、返回值传递
# - 变量可以指向函数
def fun_1(x):
print("in fun 1 x:", x)
return x + 1
def fun_2(x):
print("in fun 2, x:", x)
var_fun = fun_1
var_fun(1)
# - 函数名也是变量
# 那么函数名是什么呢?函数名其实就是指向函数的变量!
# 对于fun_1()这个函数,完全可以把函数名fun_1看成变量,它指向一个函数!
# 如果把fun_1指向其他对象,会有什么情况发生?
fun_1 = fun_2
fun_1(2)
# -- 高阶函数:参数还有指向函数的变量
def high_fun(x, y, f):
print("in hight fun :", f(x) + f(y))