供个人学习笔记回顾时使用.
print()输出 input()输入
r'
xxx'
xxx字符不需要转义
'''
xxx'''
xxx中间字符支持跨行
由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。
Python对bytes类型的数据用带b前缀的单引号或双引号表示:
x = b'ABC'
以Unicode表示的str通过encode()方法可以编码为指定的bytes,例如:
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:
len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数:
'中文'.encode('utf-8')
b'ABC'.decode('ascii')
# 如果bytes中只有一小部分无效的字节,可以传入errors='ignore'忽略错误的字节:
b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
len('中文'.encode('utf-8'))
# 6
模板字符串%
print('Hi, %s, you have $%d.' % ('你好', 1000000))
# format函数也可以
'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
# 'Hello, 小明, 成绩提升了 17.1%'
%d, %s, %f, %x - 十六进制, 其余和C语言一样
%s会自动把数字也转换成字符串, 模板字符串里面如果想表达%
的话就写%%
循环不用多说了, 一个样, for
…in
, while
, 记得最后加个:
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
n = 1
while n <= 100:
print(n)
n = n + 1
print('END')
# 判断一个对象是可迭代对象
from collections import Iterable
isinstance('abc', Iterable) #true
# 获取数组下标
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
# 循环 + range高级用法1
list(range(1, 11))
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 循环 + range高级用法2
[x * x for x in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 循环 + range高级用法3
[x * x for x in range(1, 11) if x % 2 == 0]
# [4, 16, 36, 64, 100]
# 双层循环 + range
[m + n for m in 'ABC' for n in 'XYZ']
# ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
条件判断, 这个稍有不同, 为if
xxx elif
xxx
list
classmates = ['Michael', 'Bob', 'Tracy']
# list是一个可变的有序表,所以,可以往list中追加元素到末尾:
classmates.append('Adam')
['Michael', 'Bob', 'Tracy', 'Adam']
# 把元素插入到指定的位置,比如索引号为1的位置:
classmates.insert(1, 'Jack')
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
# 要删除list末尾的元素,用pop()方法:
classmates.pop()
['Michael', 'Jack', 'Bob', 'Tracy']
# 删除指定位置的元素,用pop(i)方法,其中i是索引位置:
classmates.pop(1)
['Michael', 'Bob', 'Tracy']
# 切片, 类似JS中的Slice, 如果第一个索引是0, 还可以简写classmates [:2]
classmates [0:2]
['Michael', 'Bob']
# -1就是最后一位
classmates [-1]
['Tracy']
# 切片的高级用法
# 先创建一个数字比较多的list 从0-99的变量L
L = list(range(100))
# 前10个数,每两个取一个:
L[:10:2]
[0, 2, 4, 6, 8]
# 所有数,每5个取一个:
L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
# 只写[:]就可以原样复制一个list:
L[:]
[0, 1, 2, 3, ..., 99]
不可变tuple
#tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改.
classmates = ('Michael', 'Bob', 'Tracy')
dict和js里面的Map差不多, 就是key-value, 不过有点不同的是, 不能用list和dict作为key, 这点有点不是很清楚, 不是拿地址做的key吗?
# 写法也和JS里面的对象一样
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
d['Michael']
# in操作符, 判断一个key是否是在一个dict当中
'Thomas' in d
# dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value
d.get('Thomas', -1)
# 要删除一个key,用pop(key)方法,对应的value也会从dict中删除:
d.pop('Bob')
set和js里面的set就更像了, 数组去重
s = set([1, 2, 3, 3])
# 1, 2, 3
# 添加元素
s.add(4)
# 删除
s.remove(4)
函数def是关键词, 也不需要大括号, 直接缩进搞定
def my_abs(x):
# 判断类型
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
# 如果要返回多个值可以直接, return x, y, z 这个实际上是个tuple
# 外部调用者: x, y, z = 返回多个值的函数() 即可
默认参数和Js一样, 例子如下:
def add_end(L=[]):
L.append('END')
return L
这里有一点需要注意, Python函数在定义的时候,默认参数L的值就被计算出来了,即[].
因为默认参数L也是一个变量,它指向对象[].
每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
可变参数, 类似于JS中arguments的功能.
# 调用方法: calc(1, 2, 3) 或者 nums = [1, 2, 3] calc(*nums)
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
关键字参数, 传对象, python叫dict
# 调用方法1: person('Adam', 45, gender='M', job='Engineer')
# name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
# 调用方法2:
# extra = {'city': 'Beijing', 'job': 'Engineer'}
# person('Jack', 24, **extra)
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
如果要限制关键字参数的名字,就可以用命名关键字参数,不传会报错
def person(name, age, *, city, job):
print(name, age, city, job)
# 或者函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了
def person(name, age, *args, city, job):
print(name, age, args, city, job)
# 调用方法: person('Jack', 24, city='aaa', job='Engineer')
参数组合: 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数.
例:
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
和js差不多, 下面是个错误例子:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
# f1, f2, f3都是3
解决方案和js的方法一样, 这里先回顾一下js解决闭包的方法:
py这里使用方案三就可以解决
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs
f1, f2, f3 = count()
print(f1(), f2(), f3())
# 1 4 9
这里有个小tips, 如果一个函数里想要引用全局或者上个作用域的变量, 需要增加关键字
global
关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal
关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal
位置会发生错误(最上层的函数使用nonlocal
修饰变量必定会报错)
# 例子
def createCounter():
num = 0
def counter():
nonlocal num
num = num + 1;
return num
return counter
py需要关键字来声明, 例:
# 匿名函数
lambda x: x * x
# 实际函数
def f(x):
return x * x
和js没啥区别, 下面是个例子
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log()
def now():
print('1111')
# now = log(now)
>>> now()
# call now():
# 1111
也可以三层
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('liu')
def now():
print('1111')
# now = log('execute')(now)
>>> now()
# liu now():
# 1111
这个感觉是一种编程思想, 函数默认一些参数的快捷键, 没什么难度
当函数的参数个数太多,需要简化时,使用
functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
def int2(x, base=2):
return int(x, base)
等同于
import functools
int2 = functools.partial(int, base=2)
max2 = functools.partial(max, 10)
max2(5, 6, 7)
等用于
args = (10, 5, 6, 7)
max(*args)
和JS版本的generator差不多. 语法主要是yield和next
# 创建一个generate, 只要把一个列表生成式的[]改成()
g = (x * x for x in range(10))
# 例子: 计算斐波拉契数列
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
# 调用方法1:
result = fib(5)
result.next()
# 调用方法2:
for n in fib(6):
print(n)
# 获取generate函数的return值
g = fib(6)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
和Js的用法一毛一样:
map()函数接收两个参数,一个是函数,一个是Iterable
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r)
# [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce()函数需要额引入, 一个参数的这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算.
from functools import reduce
def add(x, y):
return x + y
r = reduce(add, [1, 3, 5, 7, 9])
print(r)
# 25
filter()和上面两个函数传参都一样
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]
sorted函数传参和上面这三个有点不同
第一个参数是数组, 第二个参数用来操纵数据里的每一项, 第三个参数是否倒排
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[1]
L2 = sorted(L, key=by_name, reverse = True)
print(L2)
# [('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]
模块使用方式和js有不同的地方.
定义一个模块
第1行和第2行是标准注释,第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件本身使用标准UTF-8编码;
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;
第6行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;
当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = 'asd'
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
test()
a = 1
_a = 2
使用模块
import hello
hello.test() # Hello, world!
print(hello.a) # 1
print(hello._a) # 2
py模块搜索规则
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中:
import sys
print(sys.path)
如果我们要添加自己的搜索目录,有两种方法:
一是直接修改sys.path,添加要搜索的目录, 这种方法是在运行时修改,运行结束后失效。
import sys
sys.path.append('/Users/michael/my_py_scripts')
print(sys.path)
第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。
如果一个文件夹下都是模块, 需要使用一个文件来声明这是个模块目录
mycompany
├─ __ init __.py
├─ abc.py
└─ xyz.py
如果想调用abc模块,则: mycompany.abc
init文件里是mycompany模块的代码
字数太多, 有点卡了… 新开一个博客
reference links: