7
您可以关注公众号《Python数据结构》了解更多知识。

扫码关注《Python数据结构》

i = i+1 和 i += 1

  • 对于不可变数据类型(str、int、tuple)
由于本身是不可变数据类型,执行后都会生产新的对象
x = 1
print(id(x))  # 1510566928
x += 1
print(id(x))  # 1510566960
---------------------------
x = 1
print(id(x))  # 1510566954
x = x + 1
print(id(x)) # # 1510566998
  • 可变数据类型情况(list、dict)
可以看到 使用 += 并不会改变对象的内存地址
x = [1, 2]
print(id(x))  # 2701823038387
x = x + [3, 4]
print(id(x))  # 2701823038334
------------------
x = [1, 2]
print(id(x))  # 2701823038344
x += [3, 4]
print(id(x))  # 2701823038344
  • 注意
n = n + n 作用域问题内部为[1, 2, 1, 2], 外部仍为[1, 2]
def num(n):
    n = n + n
x = [1, 2]
num(x)
print(x)  # [1, 2]
--------------------
def num(n):
    n += n
x = [1, 2]
num(x)
print(x)  # [1, 2, 1, 2]

内建函数

zip

key = [key for key in dict(zip(('a','b','c','d','e'),(1,2,3,4,5))) ]
print(key)
--------------------------------------------------------
['a', 'b', 'c', 'd', 'e']
A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = [i for i in A1 if i in A0]
A3 = [A0[s] for s in A0]
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
-------------------------------------------------------------
A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 3, 2, 5, 4]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

闭包

作用——保存局部信息不被销毁。
def num2(n):
    i = 1
    def num_in():
        nonlocal i
        i = i + n
        print(i)
    return num_in

i = 0
start = num2(3)
while i<5:
    start()
    i += 1

匿名函数(lambda)

与正常写法相比,使用匿名函数相当简洁
  • map() 遍历所有
a = [1, 2, 3]
x = []
for each in a:
    x.append(each+1)

print(x)
### 使用map(func, iterable)
print(list(map(lambda x: x+1, a)))
  • reduce(func, seq) 积累每次计算的值
def num(x, y):
    return x + y
print(reduce(num, [1, 2, 3, 4]))
--------------------------
print(reduce(lambda x, y: x*y, [1, 2, 3, 4]))
  • filter(func, iterable) 过滤满足条件的值
print(list(filter(lambda x: x%2==0,range(10))))

进程和线程的区别

  • 进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。
  • 线程是程序执行时的最小单位,它是进程的一个执行流。
  • 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵
  • 线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多
  • 进程实现
from multiprocessing import Pool
import time
import random
import os


def work(msg):
    start = time.time()
    print("work{}开始执行,id为{}".format(msg, os.getpid()))
    time.sleep(random.random()*2)
    stop = time.time()
    print("work{}耗时{}.".format(msg, stop-start))

p = Pool()
for i in range(10):
    # 非堵塞运行
    p.apply_async(work, args=(i,))
    # 堵塞进行
    # p.apply(work, args=(i,))


print("开始")
p.close()
p.join()
print("结束")
  • 线程实现
import threading
import os
from time import sleep

def sorry(i):
    print('say sorry  {}'.format(i))
    sleep(1)

if __name__ == '__main__':
    for i in range(1,10):
        t = threading.Thread(target=sorry, args=(i,))
        t.start()

协程

协程之前我们明白Python的进程和线程,这里我们来说一下协程
  • 子程序切换不是线程切换,而是由程序自身控制
  • 没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显
  • 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁
  • 协程实现
def custumer():
    r = ''
    while True:
        n = yield r  # 接受send的值  返出yield的值
        if not n:
            return
        print('custer {}'.format(n))
        r = 'done'

def produce(c):
    c.send(None)  # 启动
    n = 0
    while n < 5:
        n += 1
        print('custer {}'.format(n))
        r = c.send(n)
        print('custer return {}'.format(r))
    c.close()

c = custumer()
produce(c)

GIL

Python并不支持真正意义上的多线程。Python中提供了多线程包,但是如果你想通过多线程提高代码的速度,使用多线程包并不是个好主意。Python中有一个被称为Global Interpreter Lock(GIL)的东西,它会确保任何时候你的多个线程中,只有一个被执行。线程的执行速度非常之快,会让你误以为线程是并行执行的,但是实际上都是轮流执行。经过GIL这一道关卡处理,会增加执行的开销。这意味着,如果你想提高代码的运行速度,使用threading包并不是一个很好的方法。
不过还是有很多理由促使我们使用threading包的。如果你想同时执行一些任务,而且不考虑效率问题,那么使用这个包是完全没问题的,而且也很方便。但是大部分情况下,并不是这么一回事,你会希望把多线程的部分外包给操作系统完成(通过开启多个进程),或者是某些调用你的Python代码的外部程序(例如Spark或Hadoop),又或者是你的Python代码调用的其他代码(例如,你可以在Python中调用C函数,用于处理开销较大的多线程工作)。

copy

Python拷贝分为深拷贝和浅拷贝
  • 浅拷贝对子对象不拷贝,深拷贝全部拷贝
l1 = [1, 2, [3, 4]]
l2 = copy.copy(l1)
l1.append(5)
l1[2].append(5)  # 子对象 改变
print(l1)
print(l2)
--------------
[1, 2, [3, 4, 5], 5]
[1, 2, [3, 4, 5]]
  • 深拷贝完是两个完全不相干的对象
l1 = [1, 2, [3, 4]]
l2 = copy.deepcopy(l1)
l1.append(5)
l1[2].append(5)
print(l1)
print(l2)
--------------
[1, 2, [3, 4, 5], 5]
[1, 2, [3, 4]]

垃圾回收机制

  • 引用计数
import sys
# 请在Python解释器下运行  为 2  创建一次 调用一次
str1 = 'hello world'
print(sys.getrefcount(str1))
  • 分代技术
Python默认定义了三代对象集合,索引数越大,对象存活时间越长
Python中使用了某些启发式算法(heuristics)来加速垃圾回收。例如,越晚创建的对象更有可能被回收。对象被创建之后,垃圾回收器会分配它们所属的代(generation)。每个对象都会被分配一个代,而被分配更年轻代的对象是优先被处理的。
  • 引用循环
垃圾回收器会定时寻找这个循环,并将其回收。举个例子,假设有两个对象o1和o2,而且符合o1.x == o2和o2.x == o1这两个条件。如果o1和o2没有其他代码引用,那么它们就不应该继续存在。但它们的引用计数都是1。

is和==

# is 比较的是内存地址   == 比较内容和数据类型
a = [1, 2, 3]
b = a
print(a is b)
print(a == b)

c = copy.deepcopy(a)
print(a is c)
print(a == c)
-------------
True
True
False
True

文件操作

read,readline和readlines

read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历

递归输出文件

import os

def print_directory_contents(sPath):
    for sChild in os.listdir(sPath):
        sChildPath = os.path.join(sPath, sChild)
        if os.path.isdir(sChildPath):
            print_directory_contents(sChildPath)
        else:
            print(sChildPath)
print_directory_contents('F:\\GZ\\mxgController')

Fibonacci数列

def fab(n):
    a, b = 0, 1
    while n:
        yield b
        a, b = b, a+b
        n -= 1

内存管理

  • 小整数缓存池
a = 1
b = 1
print(a is b) # True
  • 短字符串
# True
a = "good"
b = "good"
print(a is b)

# False
a = "very good morning"
b = "very good morning"
print(a is b)

# False
a = []
b = []
print(a is b)

函数调用

函数赋值会开辟新空间,即[] 和 [3, 2, 1]内存地址不一样,前者引用,后者覆盖
def f(x, l=[]):
    for i in range(x):
        l.append(i*i)
    print(l)

f(2) # [0, 1]
f(3,[3,2,1]) # [3, 2, 1, 0, 1, 4]  # 自己单独开辟
f(3) # [0, 1, 0, 1, 4]  # 和f(2)共用

三目

if/else

# 若果 a>b 成立  就输出  a-b  否则 a+b
h = a-b if a>b else a+b

and/or

### and 所有值都为真,返回最后一个真;若有一个假,返回第一个假
print(2 and 1 and 3)  # 3
print(1 and 3 and 0 and 4) # 0
print(1 and  0 and 3/0) # 0
### or  所有值都为假,返回最后一个假;若有一个真,返回第一个真
print(0 or 1 or 1/0)
print(0 or '')
### 如果 a<b 返回True 否则返回a+b
print((a-b) and (a<b) or (a+b))

设计模式

单例---类方法方式

class Single():
    def __init__(self, name):
        self.name = name
    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Single, "_instance"):
            Single._instance = Single(*args, **kwargs)
        return Single._instance
s1 = Single.instance('Gage')
s2 = Single.instance()
print(s1)
print(s2)

单例---new方式

class Single(object):
    __isstance = None
    __first_init = False
    def __new__(cls, *args, **kwargs):
        if not cls.__isstance:
            cls.__isstance = object.__new__(cls)
        return cls.__isstance
    def __init__(self, name):
        if not self.__first_init:
            self.name = name
            Singleton.__first_init = True
a = Single('a')
b = Single('b')
print(id(a))
print(id(b))

工厂模式

# 首先定义一个抽象基类
class CarStore(object):

    # 定义生产汽车的方法
    def createcar(self, name):
        pass

    # 根据类型去生产车
    def order(self, name):
        self.car = self.createcar(name)
        self.car.move()


# 定义4s店  实现抽象类
class AoDiCarStore(CarStore):

    def createcar(self, name):
        self.factory = CarFactory()
        return self.factory.createcar(name)


# 创建一个车
class AoDi():
    def move(self):
        print('移动')
# 定义一个工厂
class CarFactory():
    def createcar(self, name):
        self.name = name
        if self.name == 'AoDi':
            self.car = AoDi()
        return self.car
aodi = AoDiCarStore()
aodi.order('AoDi')

数据结构

链表成对调换

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    # @param a ListNode
    # @return a ListNode
    def swapPairs(self, head):
        if head != None and head.next != None:
            next = head.next
            head.next = self.swapPairs(next.next)
            next.next = head
            return next
        return head

单链表反转

class Node(object):
    def __init__(self, data=None, next=None):
        self.data = data
        self.next = next

link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))

def rev(link):
    pre = link
    cur = link.next
    pre.next = None
    while cur:
        tmp = cur.next
        cur.next = pre
        pre = cur
        cur = tmp
    return pre

root = rev(link)
while root:
    print root.data
    root = root.next

快速排序

def quicksort(list):
    if len(list)<2:
        return list
    else:
        midpivot = list[0]
        lessbeforemidpivot = [i for i in list[1:] if i<=midpivot]
        biggerafterpivot = [i for i in list[1:] if i > midpivot]
        finallylist = quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot)
        return finallylist

print quicksort([2,4,6,7,1,2,5])

二分搜索

#coding:utf-8
def binary_search(list,item):
    low = 0
    high = len(list)-1
    while low<=high:
        mid = (low+high)/2
        guess = list[mid]
        if guess>item:
            high = mid-1
        elif guess<item:
            low = mid+1
        else:
            return mid
    return None
mylist = [1,3,5,7,9]
print binary_search(mylist,3)

扫码关注《Python数据结构》


嘉美伯爵
56 声望7 粉丝

健身和旅行必须有一个在路上