最近在学Python,主要代码整理自廖雪峰博客:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
基础
代码语言:javascript复制print 'I'm "OK"!'
a = 123 # a是整数
print a
a = 'ABC' # a变为字符串
print a
a = 100
if a >= 0: # 注意冒号
print a
else:
print -a
# int转成string,函数int(string)
# string转成int,函数str(number)
print len(u'ABC')
print 'Hi, %s, you have $%d.' % ('Michael', 1000000)
print 'Age: %s. Gender: %s' % (25, True)
classmates = ['Michael', 'Bob', 'Tracy']
classmates.append('Adam')
classmates.insert(1, 'Jack')
classmates.pop()
classmates.pop(1)
classmates[1] = 123 # 类型可以不同
# 相等的
print classmates
print classmates[len(classmates) - 1] == classmates[-1]
print classmates[len(classmates) - 2] == classmates[-2]
# tuple和list非常类似,但是tuple一旦初始化就不能修改,没有append(),insert()这样的方法
# 可以正常地使用classmates[-1],但不能赋值成另外的元素
t = ('Michael', 'Bob', 'Tracy')
t = (1,); # 只有1个元素的tuple定义时必须加一个逗号,,来消除歧义
t = (1, 2)
print t
# 如果在某个判断上是True,把该判断对应的语句执行后,就忽略掉剩下的elif和else
# 下面打印 teenager
age = 20
if age >= 6:
print 'teenager'
elif age >= 18:
print 'adult'
else:
print 'kid'
sum = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
sum = sum x
print sum
sum = 0
for x in range(101):
sum = sum x
print sum
sum = 0
n = 99
while n > 0:
sum = sum n
n = n - 2
print sum
# 打印
# name = raw_input('please enter your name: ')
# print 'hello,', name
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
print d['Michael']
d['Adam'] = 67
print d['Adam']
# 要避免key不存在的错误
print 'Thomas' in d
print d.get('Thomas')
print d.get('Thomas', -1)
d.pop('Bob')
key = [1, 2, 3]
# key的对象就不能变,而list是可变的,就不能作为key
# d[key] = 'a list'
print d
# 要创建一个set,需要提供一个list作为输入集合
s1 = set([1, 2, 3])
# 重复元素在set中自动被过滤
s1 = set([1, 1, 2, 2, 3, 3])
s1.add(4)
s1.remove(4)
s2 = set([2, 3, 4])
# 交集、并集
print s1 & s2, s1 | s2
# 对于可变对象,比如list,对list进行操作,list内部的内容是会变化的
a = ['c', 'b', 'a']
a.sort()
print a
# 对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。
# 相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
a = 'abc'
b = a.replace('a', 'A')
print a, b
函数
代码语言:javascript复制# 函数
# 比较函数
print cmp(1, 2)
# 数据类型转换
print int('123')
print int(12.34)
str(1.23)
unicode(100)
bool(1)
bool('')
# 定义函数,如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。
# return None可以简写为return,函数执行完毕没有return语句时,自动return None。
# 只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance实现
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
a = my_abs # 变量a指向abs函数
print a(-1) # 所以也可以通过a调用abs函数
# 空函数
# 如果想定义一个什么事也不做的空函数,可以用pass语句
# pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来
# 缺少了pass,代码运行就会有语法错误。
def nop():
pass
# 可以返回多个值,实际是返回tuple,这样写起来方便
def move(x, y, step, angle=0):
nx = x step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
x, y = move(100, 100, 60, math.pi / 6)
print x, y
r = move(100, 100, 60, math.pi / 6)
print r
# 默认参数,必选参数在前,默认参数在后
# 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print power(5), power(5, 3)
def enroll(name, gender, age=6, city='Beijing'):
print 'name:', name
print 'gender:', gender
print 'age:', age
print 'city:', city
print enroll('Sarah', 'F')
print enroll('Bob', 'M', 7)
# 当不按顺序提供部分默认参数时,需要把参数名写上
print enroll('Adam', 'M', city='Tianjin')
def add_end(L=[]):
L.append('END')
return L
print add_end()
print add_end() # ['END', 'END'],不对
# 默认参数必须指向不变对象!,修改上面的例子,否则运行会有逻辑错误!
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
# 可变参数,在参数前面加了一个*号
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum n * n
return sum
print calc(1, 2)
print calc()
# 如果已经有一个list或者tuple,要调用一个可变参数怎么办?
nums = [1, 2, 3]
print calc(nums[0], nums[1], nums[2])
print calc(*nums)
# 关键字参数,可以扩展函数的功能
# 比如,在person函数里,我们保证能接收到name和age这两个参数,
# 但是,如果调用者愿意提供更多的参数,我们也能收到
def person(name, age, **kw):
print 'name:', name, 'age:', age, 'other:', kw
person('Michael', 30)
# name: Michael age: 30 other: {}
person('Bob', 35, city='Beijing')
# name: Bob age: 35 other: {'city': 'Beijing'}
person('Adam', 45, gender='M', job='Engineer')
# name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
kw = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, city=kw['city'], job=kw['job'])
person('Jack', 24, **kw)
# 参数组合
# 在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用
# 注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。
def func(a, b, c=0, *args, **kw):
print 'a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw
print func(1, 2)
# a = 1 b = 2 c = 0 args = () kw = {}
print func(1, 2, c=3)
# a = 1 b = 2 c = 3 args = () kw = {}
print func(1, 2, 3, 'a', 'b')
# a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
print func(1, 2, 3, 'a', 'b', x=99)
# a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
# 要注意定义可变参数和关键字参数的语法:
# *args是可变参数,args接收的是一个tuple;
# **kw是关键字参数,kw接收的是一个dict。
args = (1, 2, 3, 4) # tuple
kw = {'x': 99} # dict
print func(*args, **kw)
# a = 1 b = 2 c = 3 args = (4,) kw = {'x': 99}
# 递归
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
# 尾递归
def fact(n):
return fact_iter(n, 1)
# 切片
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
r = []
n = 3
for i in range(n):
r.append(L[i])
# 迭代
print r
# 切片(Slice)操作符,取前3个元素,用一行代码就可以完成
print L[0:3]
# 如果第一个索引是0,还可以省略
print L[:3]
# 取倒数第一个元素
print L[-2:-1]
# 取后俩个元素
print L[-2:]
# 原样复制一个list:
print L[:]
# tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
print (0, 1, 2, 3, 4, 5)[:3]
print 'ABCDEFG'[:3]
# 只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代
# 遍历key
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
print key
# 遍历value
for value in d.itervalues():
print value
# 遍历key,value
for k, v in d.iteritems():
print k, '=', v
for ch in 'ABC':
print ch
from collections import Iterable
print isinstance([1, 2, 3], Iterable) # list是否可迭代
print isinstance('abc', Iterable) # str是否可迭代
print isinstance(123, Iterable) # 整数是否可迭代,false
print isinstance(x, str) # 判断一个变量是不是字符串
# 这样就可以在for循环中同时迭代索引和元素本身
for i, value in enumerate(['A', 'B', 'C']):
print i, value
for x, y in [(1, 1), (2, 4), (3, 9)]:
print x, y
# 列表生成式
print range(1, 11)
L = []
# [1x1, 2x2, 3x3, ..., 10x10]
for x in range(1, 11):
L.append(x * x)
print [x * x for x in range(1, 11)]
# 筛选出仅偶数的平方
print [x * x for x in range(1, 11) if x % 2 == 0]
# 两层循环,可以生成全排列
print [m n for m in 'ABC' for n in 'XYZ']
# 列出当前目录下的所有文件和目录名
print [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
L = ['Hello', 'World', 'IBM', 'Apple']
# 一个list中所有的字符串变成小写
print [s.lower() for s in L]
# 生成器:如果列表元素可以按照某种算法推算出来,这样就不必创建完整的list,从而节省大量的空间
# 和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator
L = [x * x for x in range(10)]
g = (x * x for x in range(10))
print g.next()
for n in g:
print n
# 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
def odd():
print 'step 1'
yield 1
print 'step 2'
yield 3
print 'step 3'
yield 5
# 在执行过程中,遇到yield就中断,下次又继续执行
# 基本上从来不会用next()来调用它,而是直接使用for循环来迭代
o = odd()
print o.next()
print o.next()
print o.next()
# 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
# 函数的名字也是变量
def add(x, y, f):
return f(x) f(y)
print(add(-5, 6, abs))
def f(x):
return x * x
# map()函数接收两个参数,一个是函数,一个是Iterable,
# map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print list(r)
# for也能实现,太麻烦
L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
L.append(f(n))
print(L)
print list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
# reduce把结果继续和序列的下一个元素做累积计算
# reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
def add(x, y):
return x y
print reduce(add, [1, 3, 5, 7, 9])
# 求和运算可以直接用Python内建函数sum(),没必要动用reduce。
# print sum([1, 3, 5, 7, 9])
def fn(x, y):
return x * 10 y
print reduce(fn, [1, 3, 5, 7, 9])
def char2num(s):
digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
return digits[s]
print reduce(fn, map(char2num, '13579'))
# 简化
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def fn(x, y):
return x * 10 y
def char2num(s):
return DIGITS[s]
return reduce(fn, map(char2num, s))
# 用lambda函数进一步简化
def char2num(s):
return DIGITS[s]
def str2int(s):
return reduce(lambda x, y: x * 10 y, map(char2num, s))
print str2int('13579')
# filter()函数用于过滤序列
# 根据返回值是True还是False决定保留还是丢弃该元素
def is_odd(n):
return n % 2 == 1
print list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
def not_empty(s):
return s and s.strip()
print list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
print sorted([36, 5, -12, 9, -21])
print sorted([36, 5, -12, 9, -21], key=abs)
print sorted(['bob', 'about', 'Zoo', 'Credit'])
# 排序应该忽略大小写,按照字母序排序
print sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
print sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax n
return ax
return sum
# 闭包,函数作为返回值
# 返回的函数并没有立刻执行,而是直到调用了f()才执行。
f1 = lazy_sum(1, 3, 5, 7, 9)
f2 = lazy_sum(1, 3, 5, 7, 9)
print f1() == f2() # true,比较的值
print f1 == f2 # false,引用不同,所以f1()和f2()的调用结果互不影响。
def count():
fs = []
for i in range(1, 4):
def f():
return i * i
fs.append(f)
return fs
# 全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。
# 等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9
# 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
f1, f2, f3 = count()
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() # 1,4,9
# 匿名函数
# 冒号前面的x表示函数参数
print list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
# 匿名函数lambda x: x * x,实际上就是
def f(x):
return x * x
# 可以把匿名函数赋值给一个变量,再利用变量来调用该函数
# 也可以把匿名函数作为返回值返回
f = lambda x: x * x
print f(4)
# 假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,
# 这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
print now()
# 偏函数:当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,
# 这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
int2 = functools.partial(int, base=2)
# 不需要我们自己定义
def int3(x, base=2):
return int(x, base)
print int2('1000000')
print int3('1000000')
# 作者
__author__ = 'Michael Liao'
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
# 类似_xxx和__xxx这样的函数或变量就是非公开的(private),不应该被直接引用
# 公开greeting()函数,而把内部逻辑用private函数隐藏起来
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
面向对象
代码语言:javascript复制# 面向过程
import logging
import types
std1 = {'name': 'Michael', 'score': 98}
std2 = {'name': 'Bob', 'score': 81}
def print_score(std):
print('%s: %s' % (std['name'], std['score']))
# 面向对象
class Student(object):
def __init__(self, name, score):
self.__name = name
self.score = score
# self指向创建的实例本身,可以不传
# 实现数据的封装
def print_score(self):
print('%s: %s' % (self.__name, self.score))
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
bart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)
bart.print_score()
lisa.print_score()
print lisa.get_name(), lisa.score
class Animal(object):
def run(self):
print 'Animal is running...'
class Dog(Animal):
def run(self):
print 'Dog is running...'
class Cat(Animal):
def run(self):
print 'Cat is running...'
# 多态
def run_twice(animal):
if (isinstance(animal, Animal)):
animal.run()
else:
print "类型错误"
print run_twice(Cat())
print run_twice(Student('Bart Simpson', 59));
# 对于class的继承关系来说,使用type()就很不方便。
# 我们要判断class的类型,可以使用isinstance()函数。
print type('abc') == types.StringType
print type(u'abc') == types.UnicodeType
print type([]) == types.ListType
print type(str) == types.TypeType
print dir('ABC')
class Student(object):
pass
s = Student()
s.name = 'Michael' # 动态给实例绑定一个属性
print s.name
def set_age(self, age): # 定义一个函数作为实例方法
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s, Student) # 给实例绑定一个方法
s.set_age(25) # 调用实例方法
print s.age # 测试结果
s2 = Student() # 创建新的实例
# print s2.set_age(25) # 尝试调用方法,不能
def set_score(self, score):
self.score = score
# 为了给所有实例都绑定方法,可以给class绑定方法
Student.set_score = MethodType(set_score, None, Student)
# 定义一个特殊的__slots__变量,来限制该class能添加的属性,但对子类不起作用
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
s = Student() # 创建新的实例
s.name = 'Michael' # 绑定属性'name'
s.age = 25 # 绑定属性'age'
# s.score = 99 # 不能绑定属性'score'
# 该属性不是直接暴露的,而是通过getter和setter方法来实现
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s = Student()
s.score = 60 # OK,实际转化为s.set_score(60)
s.score # OK,实际转化为s.get_score()
# s.score = 9999
print s.score # 实际转化为s.get_score()
# 还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
# 可以多继承
# class Dog(Mammal, RunnableMixin, CarnivorousMixin):
# pass
# 定制类
# __str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name=%s)' % self.name
__repr__ = __str__
s = Student('Michael')
print s
print Student('Michael')
# 要表现得像list那样按照下标取出元素,需要实现__getitem__()方法
class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a b
return a
f = Fib()
# print f(0), f(100)
# 只有在没有找到属性的情况下,才调用__getattr__,已有的属性,不会在__getattr__中查找。
class Student(object):
def __getattr__(self, attr):
if attr == 'age':
# return 25
return lambda: 25 # 可以retrun函数,调用方式不一样了
raise AttributeError(''Student' object has no attribute '%s'' % attr)
s = Student()
print s.age()
class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
return Chain('%s/%s' % (self._path, path))
def __str__(self):
return self._path
print Chain().status.user.timeline.list
# 任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用(像方法一样)
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
s = Student('Michael')
print s()
# 怎么判断一个变量是对象还是函数呢?
# print callable(Student())
# print callable([1, 2, 3])
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
# logging模块可以非常容易地记录错误信息
def main():
try:
bar('0')
except StandardError, e:
logging.exception(e)
print 'Error!'
finally:
print 'finally...'
# 只要main()捕获到了,就可以处理
print main()
# assert的意思是,表达式n != 0应该是True,否则,后面的代码就会出错。
# 如果断言失败,assert语句本身就会抛出AssertionError:
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n
def main():
foo('0')
# 和assert比,logging不会抛出错误,而且可以输出到文件
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print 10 / n
线程
代码语言:javascript复制# 新线程执行的代码:
# 主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用LoopThread命名子线程
import threading
import time
def loop():
print 'thread %s is running...' % threading.current_thread().name
n = 0
while n < 5:
n = n 1
print 'thread %s >>> %s' % (threading.current_thread().name, n)
time.sleep(1)
print 'thread %s ended.' % threading.current_thread().name
print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name
# 线程间通讯问题(生产者消费者)
# 假定这是你的银行存款:
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)
# 需要上锁
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
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
# 创建全局ThreadLocal对象
# 每个Thread对它都可以读写student属性,但互不影响。也不用加锁
# ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,
# 这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。
local_school = threading.local()
def process_student():
print 'Hello, %s (in %s)' % (local_school.student, threading.current_thread().name)
def process_thread(name):
# 绑定ThreadLocal的student:
local_school.student = name
process_student()
t1 = threading.Thread(target=process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
# 协程
# consumer函数是一个generator(生成器),把一个consumer传入produce后:
# 首先调用c.next()启动生成器;
# 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
# consumer通过yield拿到消息,处理,又通过yield把结果传回;
# produce拿到consumer处理的结果,继续生产下一条消息;
# produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
# 整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
time.sleep(1)
r = '200 OK'
def produce(c):
c.next()
n = 0
while n < 5:
n = n 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
if __name__ == '__main__':
c = consumer()
produce(c)
IO操作
代码语言:javascript复制# os模块封装了操作系统的目录和文件操作,要注意这些函数有的在os模块中,有的在os.path模块中
# 要读取二进制文件,比如图片、视频等等,用'rb'模式打开文件
import codecs
import json
import os
import random
import threading
import time
try:
f = open('D:heihei.txt', 'r')
print f.read()
# 如果文件很小,read()一次性读取最方便;
# 如果不能确定文件大小,反复调用read(size)比较保险;
# 如果是配置文件,调用readlines()最方便
for line in f.readlines():
print(line.strip()) # 把末尾的'n'删掉
finally:
if f:
f.close()
# 上面太繁琐引入了with语句来自动帮我们调用close()方法
with open('D:heihei.txt', 'r') as f:
print f.read()
# 判断文件是否存在
if os.path.isdir(f):
pass
else:
os.makedirs(f)
# 直接读出unicode
# with codecs.open('D:/gbk.txt', 'r', 'gbk') as f:
# f.read() # u'u6d4bu8bd5'
print os.name # 操作系统名字
print os.environ
print os.getenv('PATH')
# 查看当前目录的绝对路径:
print os.path.abspath('.')
# # 在某个目录下创建一个新目录,
# # 首先把新目录的完整路径表示出来:
# os.path.join(os.path.abspath('.'), 'testdir')
# # 然后创建一个目录:
# os.mkdir(os.path.abspath('.') '/testdir')
# # 删掉一个目录:
# os.rmdir(os.path.abspath('.') '/testdir')
# 分离路径和名字
print os.path.split('/Users/michael/testdir/file.txt')
# 可以轻松拿到扩展名
print os.path.splitext('/path/to/file.txt')
# 对文件重命名(需要有这个文件)
# os.rename('test.txt', 'test.py')
# 删除文件
# os.remove('test.py')
# 列出当前目录下的所有目录
print [x for x in os.listdir('.') if os.path.isdir(x)]
# 列出所有的.py文件
print [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1] == '.py']
try:
import cPickle as pickle
except ImportError:
import pickle
# 序列化
d = dict(name='Bob', age=20, score=88)
# 方法1:pickle.dumps()方法把任意对象序列化成一个str,然后,就可以把这个str写入文件
s = pickle.dumps(d)
# 反序列化
d = pickle.loads(s)
print d
# 方法2:pickle.dump()直接把对象序列化后写入一个file-like Object:
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
# 反序列化
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print d
# 字典转化成json,也有俩种方法
d = dict(name='Bob', age=20, score=88)
s = json.dumps(d)
print json.loads(s)
# 对象序列号
class Student(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
s = Student('Bob', 20, 88)
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
# Student实例首先被student2dict()函数转换成dict,然后再被顺利序列化为JSON
print(json.dumps(s, default=student2dict))
# 把任意class的实例变为dict
s = json.dumps(s, default=lambda obj: obj.__dict__)
print(s)
# 反序列化
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
print(json.loads(s, object_hook=dict2student))
# 进程和线程
# mac里这样创建
# print 'Process (%s) start...' % os.getpid()
# pid = os.fork() # 创建一个进程
# if pid == 0:
# print 'I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())
# else:
# print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)
from multiprocessing import Process, Pool, Queue
# windows下,子进程要执行的代码
def run_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())
# 如果要启动大量的子进程,可以用进程池的方式批量创建子进程
if __name__ == '__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=run_proc, args=('test',))
print 'Process will start.'
p.start()
p.join()
print 'Process end.'
def long_time_task(name):
print 'Run task %s (%s)...' % (name, os.getpid())
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print 'Task %s runs %0.2f seconds.' % (name, (end - start))
if __name__ == '__main__':
print 'Parent process %s.' % os.getpid()
p = Pool()
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print 'Waiting for all subprocesses done...'
p.close()
p.join()
print 'All subprocesses done.'
# 进程间通信
# 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random())
# 读数据进程执行的代码:
def read(q):
while True:
value = q.get(True)
print 'Get %s from queue.' % value
if __name__ == '__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pw结束:
pw.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()
网络编程
代码语言:javascript复制# 客户端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('192.168.202.2', 9999))
# 接收欢迎消息:
print s.recv(1024)
for data in ['Michael', 'Tracy', 'Sarah']:
# 发送数据:
s.send(data)
print s.recv(1024)
s.send('exit')
s.close()
# tcp
# 服务器要能够区分一个Socket连接是和哪个客户端绑定的。
# 一个Socket依赖4项:服务器地址、服务器端口、客户端地址、客户端端口来唯一确定一个Socket。
# 创建一个socket:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('www.sina.com.cn', 80))
# 发送数据:
s.send('GET / HTTP/1.1rnHost: www.sina.com.cnrnConnection: closernrn')
# 接收数据:
buffer = []
while True:
# 每次最多接收1k字节:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = ''.join(buffer)
# 关闭连接:
s.close()
header, html = data.split('rnrn', 1)
print header
# 把接收的数据写入文件:
with open('sina.html', 'wb') as f:
f.write(html)
代码语言:javascript复制# 服务端
def tcplink(sock, addr):
print 'Accept new connection from %s:%s...' % addr
sock.send('Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if data == 'exit' or not data:
break
sock.send('Hello, %s!' % data)
sock.close()
print 'Connection from %s:%s closed.' % addr
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口:
s.bind(('192.168.202.2', 9999))
s.listen(5)
print 'Waiting for connection...'
while True:
# 接受一个新连接:
sock, addr = s.accept()
# 创建新线程来处理TCP连接:
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()