Python学习笔记

这是我学习python的过程中记录的一些东西,记录了一些python的特性以及python工程师面试过程中经常被问到的点。

第一章:Python基础

输入输出

  name = input('please enter your name: ')
  print('hello,', name)

变量类型

  n = 123               #整数
  f = 456.789         #浮点
  a = True and False or True #布尔
  b = None              #空
  s1 = 'Hello, world'   #字符串
  s3 = r'Hello, "Bart"'    #r为默认不转义
  s4 = r'''Hello,         
  Lisa!'''              #```内为自动加上换行符

编码

一般脚本前加上这两行

  #!/usr/bin/env python3
  # -*- coding: utf-8 -*-

list & tuple

  classmates = ['Michael', 'Bob', 1.23, ['asp', 'php']]     #list数据类型
  len(classmates)      
  classmates[0]
  classmates[-1]
  classmates.append('Adam')     #加在末尾
  classmates.insert(1, 'Jack')    #加在指定位置
  classmates.pop(1)       #删除制定元素并返回,默认为最后一个
  
  t = (1, 2)      #tuple数据类型,一旦指定不能改变
  t = ('a', 'b', ['A', 'B'])    #指向一个list,就不能改成指向其他对象
  t[2][0] = 'X'    #但指向的这个list本身是可变的

if

  age = 20              #nothing special
  if age >= 6:
      print('teenager')
  elif age >= 18:
      print('adult')
  else:
      print('kid')

循环

  names = ['Michael', 'Bob', 'Tracy']#第一种, for只有for...in...这种写法
  for name in names:
      print(name)
      
  while n > 0:#第二种
    sum = sum + n
    n = n - 2

dict & set

  d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}  #dict数据类型
  d['Michael'] = 80 #修改
  'Thomas' in d  #返回False
  d.get('Thomas')  #返回None
  d.pop('Bob')   #删除元素并返回

和list比较,dict有以下几个特点:

  • 查找和插入的速度极快,不会随着key的增加而变慢;
  • 需要占用大量的内存,内存浪费多
  • 要保证hash的正确性,作为key的对象就不能变
  • 在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key

还有一种数据类型set,类似于数学中的集合,反正我没用过

函数

  • 一些内置函数
  abs(-20)
  int('123')
  str(1.23)
  a = abs # 变量a指向abs函数
  a(-1)
  • 定义函数
  import math

  def move(x, y, step, angle=0):
      nx = x + step * math.cos(angle)
      ny = y - step * math.sin(angle)
      return nx, ny       #实际上是返回了一个tuple

定义函数时,需要确定函数名和参数个数;
如果有必要,可以先对参数的数据类型做检查;
函数体内部可以用return随时返回函数结果;
函数执行完毕也没有return语句时,自动return None。
函数可以同时返回多个值,但其实就是一个tuple。

  • 函数参数

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

  d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}  #dict数据类型
  d['Michael'] = 80 #修改
  'Thomas' in d  #返回False
  d.get('Thomas')  #返回None
  d.pop('Bob')   #删除元素并返回
  def f2(a, b, c=0, *args, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
  f2(1, 2, d=99, ext=None)
  a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}  #output
  • *args是可变参数,args接收的是一个tuple;

  • **kw是关键字参数,kw接收的是一个dict。

第二章:面向对象高级编程

给类和实例绑定方法

  s = Student()  
  s.name = 'Michael' # 给实例绑定属性
  def set_age(self, age): # 定义一个函数作为实例方法
    self.age = age
  from types import MethodType
  s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
  def set_score(self, score):
    self.score = score
  Student.set_score = set_score # 给对象绑定方法

使用slots

  class Student(object):
      __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

使用@property

    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()
    60
    >>> s.score = 9999
    error

python允许多重继承

定制类

  • 打印得漂亮一些
    def __str__(self):
        return 'Student object (name: %s)' % self.name
    __repr__ = __str__ # 这是在直接输入s的时候输出的东西
>>> print(Student('Michael'))
Student object (name: Michael)
  • 可以被for..in..调用
  class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration();
        return self.a # 返回下一个值
  
  • 可以被下标和切片访问
  class Fib(object):
    def __getitem__(self, n):
        if isinstance(n, int): # n是索引
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice): # n是切片
            start = n.start
            stop = n.stop
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L
  • 动态返回属性或者方法
class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99
        # 一个非常有用的用法,就是不判断attr,然后操作attr返回一个东西
  • __call__,直接调用实例
class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)
调用方式如下:

>>> s = Student('Michael')
>>> s() # self参数不要传入
My name is Michael.

使用元类

  • type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义

  • 正常情况下,我们都用class Xxx...来定义类,但是,type()函数也允许我们动态创建出类来

  >>> def fn(self, name='world'): # 先定义函数
...     print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>
  • 如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。连接起来就是:先定义metaclass,就可以创建类,最后创建实例。
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

闭包

  def line_conf(a, b):
      def line(x):
          return a*x + b
      return line
  
  line1 = line_conf(1, 1)
  line2 = line_conf(4, 5)
  print(line1(5), line2(5))
  • 这个例子中,函数line与环境变量a,b构成闭包。

  • 所谓的闭包是一个包含有环境变量取值的函数对象。

python内存管理

  • Python的内置函数id()。它用于返回对象的身份(identity)。其实,这里所谓的身份,就是该对象的内存地址。
  a = 1
  b = 1
  
  print(id(a)) #一样的
  print(id(b)) #一样的
  • 为了检验两个引用指向同一个对象,我们可以用is关键字。is用于判断两个引用所指的对象是否相同。
  # True
  a = 1
  b = 1
  print(a is b)
  # 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)
  • 在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。
    我们可以使用sys包中的getrefcount(),来查看某个对象的引用计数。

  • 当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动。

  • Python将所有的对象分为0,1,2三代。所有的新建对象都是0代对象。当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象。垃圾回收启动时,一定会扫描所有的0代对象。如果0代经过一定次数垃圾回收,那么就启动对0代和1代的扫描清理。当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描。

  import gc
  gc.set_threshold(700, 10, 5)
  # 第一个是多少个对象开始一次回收,第二个是0代10次1代一次,第三个是1代5次2代一次
  • 为了回收这样的引用环,Python复制每个对象的引用计数,可以记为gc_ref。假设,每个对象i,该计数为gc_ref_i。Python会遍历所有的对象i。对于每个对象i引用的对象j,将相应的gc_ref_j减1。在结束遍历后,gc_ref不为0的对象,和这些对象引用的对象,以及继续更下游引用的对象,需要被保留。而其它的对象则被垃圾回收。

  • JAVA则是从栈出发,所有没被引用到的都会被删除。

第三章:进程和线程

多进程

  • multiprocessing模块就是跨平台版本的多进程模块。

  • 一种方法是os.fork(),一种方法如下

from multiprocessing import Process
import os

# 子进程要执行的代码
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('Child process will start.')
    p.start()
    p.join()
    print('Child process end.')
  • 大量进程时用进程池
from multiprocessing import Pool
import os, time, random

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(4)
    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.')
  • 如果子进程不是自身,而是一个外部进程,则需要import subprocess

  • 进程间通信

  • Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。我们以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据。

多线程

  • 在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。

  • Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

ThreadLocal

  • 一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。

分布式

  • Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。一个服务进程可以作为调度者,将任务分布到其他多个进程中,依靠网络通信。由于managers模块封装很好,不必了解网络通信的细节,就可以很容易地编写分布式多进程程序。

  • 举个例子:如果我们已经有一个通过Queue通信的多进程程序在同一台机器上运行,现在,由于处理任务的进程任务繁重,希望把发送任务的进程和处理任务的进程分布到两台机器上。怎么用分布式进程实现?

  • 原有的Queue可以继续使用,但是,通过managers模块把Queue通过网络暴露出去,就可以让其他机器的进程访问Queue了。

第四章:错误处理

单元测试

  • 为了编写单元测试,我们需要引入Python自带的unittest模块。

文档测试

  • 就是将测试直接写在类的定义中,又可以当示例,又可以直接运行测试。

  • doctest非常有用,不但可以用来测试,还可以直接作为示例代码。通过某些文档生成工具,就可以自动把包含doctest的注释提取出来。用户看文档的时候,同时也看到了doctest。

第五章:科学计算

numpy

# 多维数组切片
a = np.array([[11, 12, 13, 14, 15],
              [16, 17, 18, 19, 20],
              [21, 22, 23, 24, 25],
              [26, 27, 28 ,29, 30],
              [31, 32, 33, 34, 35]])
              
print(a[0, 1:4]) # >>>[12 13 14]
print(a[1:4, 0]) # >>>[16 21 26]
print(a[::2,::2]) # >>>[[11 13 15]
                  #     [21 23 25]
                  #     [31 33 35]]
print(a[:, 1]) # >>>[12 17 22 27 32]
# 数组属性
print(type(a)) # >>><class 'numpy.ndarray'>
print(a.dtype) # >>>int64
print(a.size) # >>>25
print(a.shape) # >>>(5, 5)
print(a.itemsize) # >>>8
print(a.ndim) # >>>2
print(a.nbytes) # >>>200

scipy

  • SciPy是一款方便、易于使用、专为科学和工程设计的Python工具包.它包括统计,优化,整合,线性代数模块,傅里叶变换,信号和图像处理,常微分方程求解器等等
from scipy.optimize import leastsq
plsq = leastsq(residuals, p0, args=(y1, x))

theano快速入门

常用的数据类型

数值:iscalar(int类型的变量)、fscalar(float类型的变量)
一维向量:ivector(int 类型的向量)、fvector(float类型的向量)、
二维矩阵:fmatrix(float类型矩阵)、imatrix(int类型的矩阵)
三维float类型矩阵:ftensor3  
四维float类型矩阵:ftensor4

定义函数,求偏导数

# -*- coding: utf-8 -*-
import theano
import numpy as np
x = theano.tensor.fscalar('x')#声明一个int类型的变量x  
y = theano.tensor.pow(x,3)#定义y=x^3  
f = theano.function([x],y)#定义函数的自变量为x(输入),因变量为y(输出)  
print f(2)#计算当x=2的时候,函数f(x)的值
dx = theano.grad(y,x) # 偏导数函数
f2 = theano.function([x],dx) # 定义函数f,输入为x,输出为s函数的偏导数  

共享变量

  • 在程序中,我们一般把神经网络的参数W、b等定义为共享变量,因为网络的参数,基本上是每个线程都需要访问的。
  import theano  
  import numpy  
  A=numpy.random.randn(3,4);#随机生成一个矩阵  
  x = theano.shared(A)#从A,创建共享变量x  
  print x.get_value() #通过get_value()、set_value()可以查看、设置共享变量的数值。
  
  #coding=utf-8  
  import theano  
  w= theano.shared(1)#定义一个共享变量w,其初始值为1  
  x=theano.tensor.iscalar('x')  
  f=theano.function([x], w, updates=[[w, w+x]]) #定义函数自变量为x,因变量为w,当函数执行完毕后,更新参数w=w+x  
  print f(3)#函数输出为w  
  print w.get_value()#这个时候可以看到w=w+x为4 

逻辑回归中求导

    g_W = T.grad(cost=cost, wrt=classifier.W)
    g_b = T.grad(cost=cost, wrt=classifier.b)
    updates = [
    (param, param - learning_rate * gparam)
    for param, gparam in zip(classifier.params, gparams)
    ]
    然后train的过程中就可以更新了

theano写神经网络

  1. 构建从输入到输出的数学表达式
  2. 定义好loss func
  3. 写好update
  4. 准备好输入输出
  5. 然后就可以train了,反向传导全部都交给theano.tensor.grad
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,459评论 0 6
  • python学习笔记 声明:学习笔记主要是根据廖雪峰官方网站python学习学习的,另外根据自己平时的积累进行修正...
    renyangfar阅读 3,016评论 0 10
  • 教程总纲:http://www.runoob.com/python/python-tutorial.html 进阶...
    健康哥哥阅读 2,002评论 1 3
  • 多任务的实现有3种方式: 多进程模式; 多线程模式; 多进程+多线程模式。 多进程 Unix/Linux操作系统提...
    WesleyLien阅读 1,748评论 0 3
  • 瑟瑟的初冬,难得阳光明媚,临时决定来次郊游,就近走走看看。 背起背包,出发了! 冬日暖阳竟然没有穿过河面的雾纱,临...
    爱宝丫阅读 106评论 5 4