笔者的上一篇python文章阅读量不错,看来python爱好者很多,所以再写一篇,以飨读者。

先接着上一篇讲一个问题,下面这段code有没有问题?

def countcalls(func):
count = 0
def wrapper(*args, **kwargs):
count += 1
print('num of calls: {}'.format(count))
return func(*args, **kwargs)
return wrapper @countcalls
def foo(x):
print (x+1) foo(1)

运行时会发现:

UnboundLocalError: local variable 'count' referenced before assignment

原因是count在wrapper下面除非global,不然是不可见的,那么就没有初始化了。但是这是不能加global的,因为它不是global,如果移出函数外,那么结果又不对了。怎么解决呢?

python3的解决方案:

nonlocal count
count += 1

python2的解决方案:

def countcalls(func):
def wrapper(*args, **kwargs):
wrapper.count += 1
print('num of calls: {}'.format(wrapper.count))
return func(*args, **kwargs)
wrapper.count = 0
return wrapper

基于class的decorator

class PrintLog:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print ('CALLING: {}'.format(self.func.__name__))
return self.func(*args, **kwargs)

主要是__call__决定的,任何object只要定义了__call__方法就能当函数用。下面对比一下:

class PrintLog:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print ('CALLING: {}'.format(self.func.__name__))
return self.func(*args, **kwargs) def printlog(func):
def wrapper(*args, **kwargs):
print("CALLING: " + func.__name__)
return func(*args, **kwargs)
return wrapper @printlog
def f(n):
return n+2 @PrintLog
def f_class(n):
return n+2
CALLING: f
5
CALLING: f_class
5

完全等效。__call__就相当于wrapper function

magic methods

相当于是python中的syntax sugar,让+,-,*,/啥的拿过来就用,举例如下:

class Angle:
def __init__(self, value):
self.value = value % 360
def __add__(self, other_angle):
return Angle(self.value + other_angle.value) a = Angle(45)
b = Angle(90)
c = a + b
print (c.value)
135

常用方法如下:

数学运算
__add__ a + b
__sub__ a - b
__mul__ a * b
__truediv__ a/b(浮点除)
__mod__ a % b
__pow__ a ** b
位运算
__lshift__ a << b
__rshift__ a >> b
__and__ a & b
__xor__ a ^ b
__or__ a | b
比较运算
__eq__  a == b
__ne__  a != b
__lt__  a < b
__le__  a <= b
__gt__  a > b
__ge__  a >= b

举个例子:

class Money(object):
def __init__(self, dollar, cent):
self.dollars = dollar
self.cents = cent
def __str__(self):
return "$" + str(self.dollars) + "." + "{:02}".format(self.cents)
def __repr__(self):
return "Money(" + str(self.dollars) + ", " + str(self.cents) + ")"
def __add__(self, other):
cents = (self.cents + other.cents) % 100
dollars = self.dollars + other.dollars + (self.cents + other.cents)/100
return Money(dollars, cents)
def __sub__(self, other):
if self.cents < other.cents:
cents = 100 + self.cents - other.cents
dollars = self.dollars - other.dollars - 1
else:
cents = self.cents - other.cents
dollars = self.dollars - other.dollars
return Money(dollars, cents)
def __mul__(self, other):
cents = (self.cents * other) % 100
dollars = self.dollars * other + (self.cents * other) / 100
return Money(dollars, cents)
def __eq__(self, other):
return self.dollars == other.dollars and self.cents == other.cents
def __ge__(self, other):
return self.dollars >= other.dollars and self.cents >= other.cents
def __lt__(self, other):
return self.dollars < other.dollars and self.cents < other.dollars

__str__和__repr__也是会时常用到的方法,它们都会放回string。__str__被用在print()时,同时str()也会调用它。而__repr__则是告诉你如何重现这个object,python命令行交互中输入object会调用__repr__,同时repr会调用它。

python collection类型

__getitem__相当于[index]

据两个例子大家就明白了,第一个例子是关于list,第二个例子是针对dict

class UniqueList:
def __init__(self, items):
self.items = []
for item in items:
self.append(item) def append(self, item):
if item not in self.items:
self.items.append(item) def __getitem__(self, index):
return self.items[index] ul = UniqueList([2,2,2,3,3,3,4,4,4]) print ul[0]
print ul[1]
print ul[2]
2
3
4

当然在具体实现的过程中对于index 要有input check,有问题需要raise IndexException,negative index要考虑语义的支持。

class MultiDict:
def __init__(self):
self.data = {} def insert(self, key, value):
if key not in self.data:
self.data[key] = []
self.data[key].append(value) def get_values(self, key):
return self.data[key] def get(self, key):
return self.get_values(key)[-1] def __getitem__(self, key):
return self.get_values(key)[-1] md = MultiDict()
md.insert("a", 1)
md.insert("a", 2)
print md['a']#2

Iterator

回到list那个例子,你觉得下面这个语法能够工作吗?

for i in ul:
print i

答:可以的,通过__getitem__我们不小心实现了iterator,事实上只要__getitem__能够接受0,1,2,... 并且在访问越界的时候raise IndexException,就相当于实现了iterator

Iterator的另一种实现是:

def __iter__(self):
return self def __next__(self):
...
raise StopIteration
return ...

可见__getitem__显得更简洁。

掌握这些知识,你的python水平能更上一层楼(续)的更多相关文章

  1. 掌握这些知识,你的python水平能更上一层楼

    今天讲一些python中的高级用法,有助于大家更好的使用python这门语言.今天讲的这些知识是层层递进的关系,前面是后面的铺垫. 函数可变参数*args和**kwargs python支持固定参数, ...

  2. 机器学习算法的基本知识(使用Python和R代码)

    本篇文章是原文的译文,然后自己对其中做了一些修改和添加内容(随机森林和降维算法).文章简洁地介绍了机器学习的主要算法和一些伪代码,对于初学者有很大帮助,是一篇不错的总结文章,后期可以通过文中提到的算法 ...

  3. 制作一个简单的部门员工知识分享的python抽取脚本

    需求: 基于公司的文化和公司部门间以及员工之间的工作需求状态,或者想要了解某一些技能.专业方面的知识需求.促进并提高员工们的技能认知和技术水平. 详细代码如下: 先说一下存入csv表格的表头字段: 1 ...

  4. [Python][小知识][NO.2] Python 字符串跨行连接,或拆分为多行显示

    1.前言 又是一个字符串很长,但又是一种格式的小字符串直接连接而成的大字符串. 这么我们拆成多行,即美感,又易于我们修改. 例如 文件选择框中的 通配符: wildcard = "Pytho ...

  5. 深入理解python(一)python语法总结:基础知识和对python中对象的理解

    用python也用了两年了,趁这次疫情想好好整理下. 大概想法是先对python一些知识点进行总结,之后就是根据python内核源码来对python的实现方式进行学习,不会阅读整个源码,,,但是应该会 ...

  6. Python-turtle库知识小结(python绘图工具)

    turtle:海龟(海龟库) Turtle库是Python语言中一个很流行的绘制图像的函数库 使用之前需要导入库:import turtle • turtle.setup(width,height,s ...

  7. 完整的正则表达式知识汇总(Python知识不断更新)

    ## 大纲: ## 一.正则概述 1.正则是什么 正则就是一套规则,或者语法 2.正则的作用 让我们判断是否符合我们的的规则,或者根据规则找到符合规则的数据 3.使用场景 可以用正则判断我们输入的邮箱 ...

  8. 【知识碎片】python 篇

    领域:运维 网站 游戏 搜索 嵌入式 C/S软件 Openstack二次开发 绿色版:Portable Python 面向对象.解释型动态语言 env python 切换版也好使,自己寻找系统中pyt ...

  9. 剑指offer-左旋转字符串-知识迁移能力-python

    题目描述汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abcX ...

随机推荐

  1. 多项式A除以B

    这个问题我是在PAT大区赛题里遇见的.题目如下: 多项式A除以B(25 分) 这仍然是一道关于A/B的题,只不过A和B都换成了多项式.你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数 ...

  2. 故障定位之查找附近点GeoHash研讨

    随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等). 基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近. 目标:查找附近的XXX ...

  3. 帮Python找“对象”

    引言:你一定会感叹:Python还缺找对象? 毕竟"一切皆对象"是人家Python的哲学理念.不过,Python  允许程序员以纯粹的面向过程的方式来使用它,所以人们有时会忽视它那 ...

  4. Flex的 Event中属性currentTarget与target的区别

    Flex的 Event中属性currentTarget与target的区别 1.区别 (1)currentTarget是事件的处理对象(event processor) (2)target是事件的调用 ...

  5. web开发中对缓存的使用

    很久没有发表随笔了,最近工作不是太忙,抽点时间 给大家谈谈缓存吧 ; 在我从事web开发的几年实践中  接触了缓存技术 也是比较多的,在最初的 项目当中 我们用到 hibernate 的 一二级缓存, ...

  6. WKWebView 加载本地HTML显示不出网页问题,这点你注意了吗?-------完美显示

    1.首先,WKWebView的引入和创建,我这里就不做阐述,我要说的,就是解决别人不能给您解决的问题 2.WKWebView 加载本地HTML,也就是两三句代码  是吧?作为读者的您肯定也知道,也实现 ...

  7. 第二篇:数据可视化 - 基本API

    前言 数据可视化是数据挖掘非常重要的一个环节,它不单在查阅了解数据环节使用到,在整个数据挖掘的流程中都会使用到. 因为数据可视化不单可以形象地展示数据,让你对数据有更好的总体上的了解,而且还可以让你清 ...

  8. Java双等号,Equals(),HashCode()小结

    默认情况 - 双等号==,比较的是内存地址. - equals(),默认比较的是内存地址. - hashCode(),默认返回的是object的内存地址. String中方法改写的情况 经常会遇到需要 ...

  9. [Luogu2617]Dynamic Ranking

    题面戳这 类似算法总结 1.静态整体Kth 滑稽吧...sort一遍就好了. 时间复杂度\(O(nlogn)\) 空间复杂度\(O(n)\) 2.动态整体Kth 离散化后开一棵权值线段树,每个位置的值 ...

  10. 【BZOJ4372】烁烁的游戏(动态点分治)

    [BZOJ4372]烁烁的游戏(动态点分治) 题面 BZOJ 大意: 每次在一棵书上进行操作 1.将离某个点u的距离不超过d的点的权值加上w 2.询问单点权值 题解 这题和前面那一道震波几乎是一模一样 ...