Python基礎語法

最近在學Python,主要代碼整理自廖雪峯博客:html

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000git

 

基礎

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

  

函數

# 函數
# 比較函數
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)

  

面向對象

# 面向過程
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

  

線程

# 新線程執行的代碼:
# 主線程實例的名字叫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操做

# 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'\u6d4b\u8bd5'


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

  

網絡編程

# 客戶端
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.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
# 接收數據:
buffer = []
while True:
    # 每次最多接收1k字節:
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = ''.join(buffer)
# 關閉鏈接:
s.close()

header, html = data.split('\r\n\r\n', 1)
print header
# 把接收的數據寫入文件:
with open('sina.html', 'wb') as f:
    f.write(html)

  

# 服務端
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()
相關文章
相關標籤/搜索