python 学习笔记

运算符重载

PYTHON-进阶-魔术方法小结(方法运算符重载)

python有着像C++相似的运算符重载,只需要在类中重写__add__、sub 等方法,就可以直接对对象进行 + - 等操作,就好像内置对象一样。也可以重写__getattr__、__setattr__等方法来操作属性,initdelstrlen__等基本方法都可以重载,比较符的重载包括__cmpltgt__等,以及__getitem、__setitem__等操作索引的方法。总之,完全可以通过重载将一个类写的python之父都不认得。

coroutine

传统我们实现消费者 生产者模型 都是需要通过多线程之间 互相协作,一个线程生产,一个线程消费。协程就是将多线程的事情在一个线程里面干了。传统我们一个函数总是一个入口,一个出口,很明确。协程就是允许一个子程序内部可以中断,然后执行其他子程序,在适当的时候再返回来继续执行,即使在while True这样的函数。这样的话我们就可以生产 后就调用消费者,然后消费后再继续生产。

python 2.x中实现协程的方式 是通过generator,yield 停止一个子程序后,可以通过send(xxx) 继续执行

协程的好处:

  1. 极高的效率,不需要操作系统切换线程,只是程序内部控制

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

  1. 而且也不需要多线程的锁机制。。。因为这根本就只有一个线程嘛
  2. 通过协程也可以将一个复杂的程序分成多个相互协作的子程序,就好像unix 的管道一样,read ---> grep ---> print 这样,程序会更简单明了,复用性更高
# 简洁高效的生产消费模式

# 装饰器, 用来自动启动协程
def coroutine(func):
def go(*args, **kwargs):
g = func(*args, **kwargs)
g.send(None)
return g
return go @coroutine
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print ('consume {}'.format(n))
time.sleep(1)
r = '200 OK' def producer(target):
while True:
n = random.randint(1, 100)
print ('produce {}'.format(n))
r = target.send(n)
print ('consumer return {}'.format(r)) if __name__ == '__main__':
producer(consumer())

generator

generator 跟普通的方法差不多,只是可以通过yield返回多个值,如下

def gen():
yield 1
yield 2 g = gen()
print g # 输出<generator object gen at 0x00000000026BCFC0>
print g.next() # 输出1
print g.next() # 输出2
print g.next() # StopIteration 异常

通过dir(g) 可以看到generator 实现了__iter__ 和 next 方法,所以generator 也是一个迭代器, 生成器可以用来简化迭代器的实现

# 简化版的小写字母生成器,相对自定义迭代器来说,真的简单多了
def lower_letters():
current = 'a'
while current <= 'z':
yield current
current = chr(ord(current) + 1) for letter in lower_letters():
print letter

iterator & iterable

python 中的for in语法,可以遍历iterable 对象,例如list,array,map等,其实就是用iter()构造了一个iterator,并捕获StopIteration异常

_iter = iter(iterableObj)
while True:
try:
x = _iter.next()
except StopIteration:
break
do_your_func(x)

iterator 和 iterable 本质上的区别是 iterator 实现了__next__(python2.x 是next)和 iter__方法,而iterable只实现了__iter__方法,通过dir([1,2]) 可以看到数组中只实现了__iter ,只是iterable对象

所以,我们可以自定义一个迭代器,只要实现了__next__ 和 iter,并且__next__ 抛出StopIteration异常

class UpperLetter(object):
def __init__(self):
self.current = 'A' def next(self):
if self.current > 'Z':
raise StopIteration() result = self.current
self.current = chr(ord(self.current) + 1)
return result def __iter__(self):
return self letters = UpperLetter()
# 自定义的迭代器可以通过for in遍历哦
for letter in letters:
print (letter)

下划线

方法前后双下划线

约定这是python中的特殊方法,通常你将覆盖这些方法,实现所需的功能,例如__init__

方法前单下划线

约定这是私有方法,外部不能访问。

对于解释器来说, from <模块/包名> import * 是无法导入以_开头的方法

拷贝

python都对象之间赋值都是拷贝引用,如果要拷贝对象,需要使用copy模块

  1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
  2. copy.deepcopy 深拷贝 拷贝对象及其子对象
userInfo = {
"resultCode": 0,
"users": {
'name': "jobs"
}
} a = userInfo
b = copy.copy(userInfo)
c = copy.deepcopy(userInfo) # 修改原来的对象
userInfo['resultCode'] = 1
userInfo['users']['name'] = 'ryan' print a
print b
print c
# 输出:
# {'resultCode': 1, 'users': {'name': 'ryan'}}
# {'resultCode': 0, 'users': {'name': 'ryan'}}
# {'resultCode': 0, 'users': {'name': 'jobs'}}

可以看到,传引用的全改了,浅拷贝的话子对象还是保留着原来的引用,所以子对象跟着改了,深拷贝岿然不动!

切片

切片是python一个很有趣的语法糖,提供了简洁的方法来取一个数组的一部分

L=[1, 2, 3,4,5]
print L[1: 3] # 取索引1到索引3,不包含索引3
print L[:] # 第一个参数不填表示第一位,最后一个参数不填表示取最后一位
print L[-2:] # 负数表示倒数第n个元素
print L[::2] # 最后一个参数表示隔几个取一次,跟range类似 # 输出
# [2, 3]
# [1, 2, 3, 4, 5]
# [4, 5]
# [1, 3, 5] # 优雅地将数组 进行分组操作,这里如果i + 3大于数组len, 切片也能自动切到最后一截哈哈
for i in range(0, len(L), 3):
print L[i: i+3]
# 输出
# [1, 2, 3]
# [4, 5]

闭包

定义

父函数中返回的函数引用了父函数中的参数或者局部变量,这个函数就称为闭包。因此,闭包也是携带状态的函数,并且它的状态可以对外隐藏起来。闭包之于父函数就好像实例之于类

闭包修改外部变量?

一般来说闭包不能修改外部变量,因为对于同名变量的修改 python 把它看做了 子函数中的 局部变量,所以你直接修改会返回UnboundLocalError: local variable 'm' referenced before assignment错误(据说在python3中可以用nolocal 声明外部变量即可修改)

闭包实现的原理

闭包函数相对于普通函数多出了一个__closure__属性,这是一个元组,这个元祖里面包含了所有闭包函数中引用到的外部变量

参考:

说说 Python 中的闭包


装饰器

装饰器就是一种特殊的闭包,通过传递一个待修饰的函数 给 修饰函数,并返回一个修饰后的函数,可以用@decoratorFunc 来简化语法,装饰器的作用就是为已经存在的函数或对象添加额外的功能

参考:

Python 的闭包和装饰器:https://segmentfault.com/a/1190000004461404

详解 Python 的装饰器

列表生成式/字典生成式(简洁美观)

[ x * x for x in list] & { x[a] : x[b] for x in list}

python 变量作用域

  1. python的作用域是一层一层向外查的,但是如果在内层想要改变外层的变量,就需要声明global,否则只是相当于定义了一个覆盖全局的局部变量,如下
var = 1

def func1():
# 此处声明 global var 解决
var = var + 1
return var print func1()
# 报错UnboundLocalError: local variable 'var' referenced before assignment
# 因为我们企图在内层改变外层的var,所以python就把他当做局部变量了,那很明显,这个var在局部并没有赋值
  1. 同样的,对于闭包,也是尽量不要在闭包中修改外部函数的变量,理由同上(可以声明nonlocal)
  2. 除了def/class/lambda之外,其他如:if/else try/except for/while并不能改变其作用域. 略坑啊,定义在这些东西里面的变量,外部是可以访问的。。。

with as 字句

用with as 字句代替之前的try .... finally fs.close()之类的语句方便了很多

tuple

tuple 就是不可变的list, 用(1, 2, 3)定义

**如果要定义只有一个元素的tuple,不能定义为(1),python把他当做数字1(括号运算),正确的写法为(1, )

参数

默认参数的坑

python 的默认参数如果为数组的话,要千万小心了

def func2(array=[]):
array.append("haha")
print array func2() # 输出 ['haha']
func2() # 输出 ['haha', 'haha']

为什么每次调用的结果都不一样? 因为默认参数的值在函数定义的时候就生成好了,所以当默认参数指向的是 可变对象如list

就会改变它的值,所以**默认参数一定要是不可变对象"",如str,int等

可变参数

要往可变参数中传入一个数组,有两种方法

def func3(*arr):
for i in arr:
print i nums = [1, 2, 3]
func3(nums[0], nums[1], nums[2]) # 不得不说,这种写法巨丑
func3(*nums) # 好看

关键字参数

可变参数在方法中就是一个tuple,而关键字参数在方法中就是一个dict,它可以扩展函数的功能,让用户自定义配置,例如sqlalchemy的create_engine(*args, **kwargs)就使我们可以根据需要定义encoding,echo等参数

同样的,要传入一个dict给可变参数的方法可以用**dict

星解

星解提供了一个很艺术化的方法来unpack一个list或dict

def test(x, y, z):
print(x, y, z) testDict = {'x': 1, 'y': 2, 'z': 3}
testList = [10, 20, 30] test(*testDict)
test(*testList) #1-> x y z
#2-> 10 20 30

python 随笔的更多相关文章

  1. python随笔--复习专用

    <!doctype html> blockquote:first-child, #write > div:first-child, #write > figure:first- ...

  2. 我的第一个Python随笔

    自学Python也很长时间了,注册博客园写了第一篇随笔.之前想过很多次,但是始终不知道该怎么开始,内容如何,现在想想,随笔嘛,是自己的想法,也自己的实践,又是自己的锻炼.话不多说,开始今天的正式内容. ...

  3. python随笔

    1. 使用iter实现接收用户多行输入 stopword = '' str = '' print('请将要添加的内容输入下方,输入空白行按回车退出程序:') for line in iter(inpu ...

  4. Python随笔------初探

    今年的双十一刚刚才过去,大多数人主要就是抢购商品,可能他们现在已经收到了他们夜以继日抢购的商品.然而对于我们做技术的,特别是做互联网技术的,我相信肯定都被双十一那天的许多技术震撼到了吧.云计算.分压式 ...

  5. Python随笔,day1

    #python中不存在单个字符的运算,只有字符串函数 >>> s="www.google.com" >>> s 'www.google.com' ...

  6. Python 随笔-1

    python的发展史: python 2.7            July 3,2010  目前业内主流使用的工业版本 主讲3.0 32bit = 内存的最大寻址空间为2*32    4G的空间 6 ...

  7. Python随笔目录

    Python 一.Python基础 Python入门 数据类型 函数(迭代器生成器三元表达式) 模块和常用内置模块 面向对象 网络编程(socket) 并发编程 ... 二.数据库 MySQL PyM ...

  8. Python 随笔之Redis

    Python学习记录 ——redis 2018-03-07 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从 ...

  9. Python随笔---深浅拷贝

    Python中为了避免某些方法的副作用(拷贝后有时更改原有数据),故存在有深浅拷贝的存在 浅拷贝导入copy方法集,使用copy_copy的方法进行 深拷贝一样导入copy方法集,使用copy_dee ...

随机推荐

  1. 对Java的初步的认识:

    学习JAVA的优势 1) Java广受欢迎 Java是世界上最受欢迎的编程语言之一,有无限多种方法使用Java.据2016年数据显示,Java被评为最受欢迎的编程语言之一2)  Java薪资比较好最新 ...

  2. mysql数据库导入sql文件时提示“Error Code: 1153 - Got a packet bigger than 'max_allowed_packet' bytes”解决办法

    向mysql数据库中导入sql文件时,如果文件过大(几百M),会提示"Error Code: 1153 - Got a packet bigger than 'max_allowed_pac ...

  3. 听翁恺老师mooc笔记(4)--指针的应用场景

    指针应用场景一:交换两个变量的值 在学习函数时,交换两个数的值,做一个swap函数,传递值进去,也可以将两个值交换过来,没问题,可是离开swap就没有用了,为什么?因为传进去的是两个值. #inclu ...

  4. 网络1711-1712班 c 语言评分总表一览

    学号 姓名 作业地址 PTA实验作业5分 PTA排名2分 阅读代码2分 总结1分 代码规范扣分-2--0 总分 是否推荐博客 1 **莹 http://www.cnblogs.com/wwwwxy12 ...

  5. 【Alpha版本】冲刺阶段 - Day1 - 启航

    Alpha 阶段成员分工及任务量 成员 分工 任务量(小时) 袁逸灏 完成app用户车辆,子弹发射,背景移动,暂停界面,音乐界面,音乐查找,音乐播放 25 刘伟康 项目进度把控.分配任务.组织会议.整 ...

  6. Alpha冲刺No.5

    一.站立式会议 在助教帮助下,优先解决404的问题,将demo移植到自己项目上. 进一步制作界面. 将已做好的内容,移植到手机做部分测试,能够在同一路由子网内登录数据库. 二.实际项目进展 已经解决了 ...

  7. node.js基础

    //安装淘宝npm镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org//require表示引包,引包就是引用自己的一个特 ...

  8. IOS webview iframe 宽度超出屏幕解决方案

    IOS 真机webview中,iframe 却不能很好地适应屏幕大小,总是超出屏幕尺寸,需要左右滚动才能看到完整页面. <div style="overflow: auto;-webk ...

  9. 同样是IT培训,为什么人家月薪过万,你才几千,问题在哪?!

    听过一句话"360行,行行转IT",虽然有些夸张,但也不难看出IT行业的火爆程度.从李总理提的"互联网+大数据"开始,中国的这场"互联网+" ...

  10. 用js 获取url 参数 页面跳转 ? 后的参数

    记得之前在原来的公司写过这个东西,但是还是忘记怎么接住参数了,只知道怎么把id传过去! 问了身边的大佬 他首先推荐了我一个链接是别人写好的方法 附上链接地址:http://blog.csdn.net/ ...