掌握这些知识,你的python水平能更上一层楼(续)
笔者的上一篇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水平能更上一层楼(续)的更多相关文章
- 掌握这些知识,你的python水平能更上一层楼
今天讲一些python中的高级用法,有助于大家更好的使用python这门语言.今天讲的这些知识是层层递进的关系,前面是后面的铺垫. 函数可变参数*args和**kwargs python支持固定参数, ...
- 机器学习算法的基本知识(使用Python和R代码)
本篇文章是原文的译文,然后自己对其中做了一些修改和添加内容(随机森林和降维算法).文章简洁地介绍了机器学习的主要算法和一些伪代码,对于初学者有很大帮助,是一篇不错的总结文章,后期可以通过文中提到的算法 ...
- 制作一个简单的部门员工知识分享的python抽取脚本
需求: 基于公司的文化和公司部门间以及员工之间的工作需求状态,或者想要了解某一些技能.专业方面的知识需求.促进并提高员工们的技能认知和技术水平. 详细代码如下: 先说一下存入csv表格的表头字段: 1 ...
- [Python][小知识][NO.2] Python 字符串跨行连接,或拆分为多行显示
1.前言 又是一个字符串很长,但又是一种格式的小字符串直接连接而成的大字符串. 这么我们拆成多行,即美感,又易于我们修改. 例如 文件选择框中的 通配符: wildcard = "Pytho ...
- 深入理解python(一)python语法总结:基础知识和对python中对象的理解
用python也用了两年了,趁这次疫情想好好整理下. 大概想法是先对python一些知识点进行总结,之后就是根据python内核源码来对python的实现方式进行学习,不会阅读整个源码,,,但是应该会 ...
- Python-turtle库知识小结(python绘图工具)
turtle:海龟(海龟库) Turtle库是Python语言中一个很流行的绘制图像的函数库 使用之前需要导入库:import turtle • turtle.setup(width,height,s ...
- 完整的正则表达式知识汇总(Python知识不断更新)
## 大纲: ## 一.正则概述 1.正则是什么 正则就是一套规则,或者语法 2.正则的作用 让我们判断是否符合我们的的规则,或者根据规则找到符合规则的数据 3.使用场景 可以用正则判断我们输入的邮箱 ...
- 【知识碎片】python 篇
领域:运维 网站 游戏 搜索 嵌入式 C/S软件 Openstack二次开发 绿色版:Portable Python 面向对象.解释型动态语言 env python 切换版也好使,自己寻找系统中pyt ...
- 剑指offer-左旋转字符串-知识迁移能力-python
题目描述汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abcX ...
随机推荐
- java复习
局部变量的作用域只在方法内部有效,在方法外无效 用类型作为形参传递会改变实参的值,但是String是特殊的引用类型,作为形参传递不会影响实参的值. HashMap非线程安全,在多个线程访问Hashta ...
- List转换成JSON对象报错(四)
List转换成JSON对象 1.具体错误如下 Exception in thread "main" java.lang.NoClassDefFoundError: org/apac ...
- axure 7.0 注册码
Axure RP 7.0注册码: 用户名:axureuser 序列号:8wFfIX7a8hHq6yAy6T8zCz5R0NBKeVxo9IKu+kgKh79FL6IyPD6lK7G6+tqEV4LG ...
- Eclipse去除网上复制下来的来代码带有的行号
一.正则表达式去除代码行号 作为开发人员,我们经常从网上复制一些代码,有些时候复制的代码前面是带有行号,如: MyEclipse本身自带有查找替换功能,并且支持正则表达式替换,使用正则替换就可以很容易 ...
- ajax异步的问题,(主要解决有时候前台打断点和不打断点结果不一样的问题,一般情况下是存在异步的问题)
一,代码 $(function() { $(".btn-submit").click(function() { if(!checkData()){ return; } var ur ...
- 异常-----freemarker.core.NonStringException
一,案例一 1.1.错误描述 <html> <head> <meta http-equiv="content-type" content=" ...
- HttpServletResponse,HttpServletRequest详解
1.相关的接口 HttpServletRequest HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletReq ...
- Unity3D 引擎基础 C# (数据结构入门) Unity3D 界面 UI(NGUI)(动画系统,导航系统)(委托与事件,常用设计模式)
Geomagic Sculpt 2016.2 Windows Software 11个月前 (01-17) 0评论 Geomagic Sculpt 触觉式三维设计 触碰您的设计使用三维工具做三维设计. ...
- Educational Codeforces Round 37
Educational Codeforces Round 37 这场有点炸,题目比较水,但只做了3题QAQ.还是实力不够啊! 写下题解算了--(写的比较粗糙,细节或者bug可以私聊2333) A. W ...
- [USACO5.4]奶牛的电信Telecowmunication
裸的最小割,拆点时要考虑清楚到底是怎么连 如果之前i->i+n,之后又x->y+n,显然出不了解 所以可以改为i+n->i 如果要输出方案 考虑每一个一个点,如果删去这个点,最小割变 ...