数据类型
整数(11)、浮点型(1.02)、字符串(‘’’ “”)、转义字符 \ r’’ 避免转义 ‘’’…’’’ 多行文字 、布尔(True False and or not)、None 、常量(大写)
isinstance(x, (int, float)) 判断x是否属于int或float类型
多个变量赋值 n, a, b = 0, 0, 1
字符串
ASCII ord() 反过来chr()
“abc”.encode(“utf-8”) 字符转字节
b’ABC’.decode(‘ascii’) 字节转字符 errors='ignore’忽略错误的字节
长度len(‘ABC’)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码
字符格式化
Hi, %s, you have $%d.’ % (‘Michael’, 1000000)
‘Hello, {0}, 成绩提升了 {1:.1f}%’.format(‘小明’, 17.125)
字符串转整数 int()
a.replace(‘a’, ‘A’)
list
list是一种有序的集合 插入和取出有序
classmates = [‘Michael’, ‘Bob’, ‘Tracy’]
len(classmates)
list[1]
classmates[-1] 最后一个元素
追加元素 classmates.append(‘Adam’)
classmates.insert(1, ‘Jack’) 插入指定位置元素
删除末尾元素 pop()方法:
除指定位置的元素,用pop(i)
所含元素可以包括各种类型
a.sort() 元素排序
tuple
有序列表叫元组,一旦初始化不能修改 尽量使用tuple来代替list
classmates = (‘Michael’, ‘Bob’, ‘Tracy’)
只有一个元素的时候 t = (1,)
条件判断
if age >= 18:
print(‘adult’)
elif age >= 6:
print(‘teenager’)
else:
print(‘kid’)
循环
所以for x in …循环就是把每个元素代入变量x,然后执行缩进块的语句。
通过下标获取list值
for i in range(n):
list[i]
while n > 0:
sum = sum + n
n = n - 2
支持break continue
range(100) 0 - 100个数
或者先转换下
for i, value in enumerate([‘A’, ‘B’, ‘C’]):
… print(i, value)
列表生成器:[x if x % 2 == 0 else -x for x in range(1, 11)]
if前面是执行体 for前面是逻辑实现
生成器延迟存储计算 有需要的时候再给值
g = (x * x for x in range(10))
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
访问也可以通过迭代器来访问
for n in g:
... print(n)
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b) // yield b 函数定义义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
a, b = b, a + b
n = n + 1
return 'done'
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
dict
字典 等同于java map
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
d[‘Adam’] = 67
‘Thomas’ in d 判断key是否存在
d.get(‘Adam’, 111) 获取key 不存在未None 默认设值 111
d.pop(‘Bob’) 删除key为Bob的元素
迭代
for key in d:
… print(key)
for value in d.values()
for k, v in d.items()
set
dic key 集合
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
s.add(4)
s.remove(4)
交集 s1 & s2
并集 s1 | s2
函数
help(abs)可以查看内置abs函数的帮助信息。
def my_abs(x):
if x >= 0:
return x
else:
return -x
空函数 pass占位符
默认参数 def power(x, n=2) 默认参数必须指向不变对象!
不按顺序提供部分默认参数 def enroll(name, gender, age=6, city=‘Beijing’) enroll(‘Adam’, ‘M’, city=‘Tianjin’)
可变参数 def calc(*numbers)
调用calc(12,32,433), 或者把list或tuple的元素变成可变参数传进去
nums = [1,2,3]
calc(*nums)
关键字参数
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
> if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
命名关键字参数,控制关键字参数个数和名称
def person(name, age, *, city, job):
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer')
参数组合 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
匿名函数 lambda x: x * x
高级特性
切片 取一个list或tuple的部分元素
L[:3] L[0:3] 切片从前面取3个
L[1:3] L[-2:-1] 第一个表示下标值 第二个减去第一个值表示取多少个 其中-号表示从末尾开始取
L[:10:2] 前10个数每隔2个取一个
L[::5] 每5个取一个
L[:] 复制list
函数式编程
map 和 reduce
reduce(lambda x, y: x * 10 + y, map(char2num, s))
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
sorted([‘bob’, ‘about’, ‘Zoo’, ‘Credit’], key=str.lower, reverse=True)
高级特性
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('execute')
def now():
print('2015-3-25')
now = log('execute')(now)
首先执行log('execute'),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数
偏函数:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单
面向对象
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
__init__ 等同于构造函数
定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用
def print_score(self):
print('%s: %s' % (self.name, self.score))
实例的变量名如果以__开头,就变成了一个私有变量(private)
一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
特殊变量
以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。
str
iter next
要表现得像list那样按照下标取出元素,需要实现__getitem__()方法:
继承多态:
class Dog(Animal):
def run(self):
print('Dog is running...')
//多重继承
class Dog(Mammal, Runnable):
pass
MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。
类信息获取:
1、判断对象类型,使用type()函数
2、判断类类型,使用isinstance()函数
3、获取获得一个对象的所有属性和方法 dir()
4、属性操作
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
类属性定义:
class Student(object):
name = 'Student'
动态给实例绑定属性和方法
>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
如需对多个实例都生效,可以绑定类
Student.set_score = set_score
限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
属性设置限定
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2015 - self._birth
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
枚举
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
@unique装饰器可以帮助我们检查保证没有重复值。
>>> print(Weekday.Tue.value)
2
异常
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')
日志打印
import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
IO读写文件
with open('/path/to/file', 'r') as f:
print(f.read())
反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
二进制 f = open('/Users/michael/test.jpg', 'rb')
字符编码 f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
写文件 with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
文件目录操作
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')
https://www.liaoxuefeng.com/wiki/1016959663602400/1017623135437088
JSON序列化
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
>>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
实例对象序列化和反序列化
print(json.dumps(s, default=lambda obj: obj.__dict__))
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x10cd3c190>
多线程和锁
import time, threading
# 假定这是你的银行存款:
balance = 0
def change_it(n):
# 先存后取,结果应该为0:
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(100000):
change_it(n)
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
balance = 0
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁的发生。
Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。
# 创建全局ThreadLocal对象:
local_school = threading.local()
ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。
正则表达式
>>> import re
>>> m = re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
>m.group(0)
>m.groups()
内置函数
时间
>>> from datetime import datetime
>>> now = datetime.now() # 获取当前datetime
>>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
>dt.timestamp() # 把datetime转换为timestamp
> print(datetime.fromtimestamp(t))
> print(datetime.utcfromtimestamp(t)) # UTC时间
> cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
> >>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
>>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
>>> now + timedelta(hours=10)
datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
>>> now - timedelta(days=1)
datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)