掌握这些知识,你的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 ...
随机推荐
- layui的几个简单使用(简单弹窗,加载效果,移除加载效果)
1.加载效果和移除加载效果 function layuiLoading(msg){ layui.use(['layer', 'form'], function(){ index = layer.loa ...
- mongodb副本集搭建过程中的问题和解决技巧
在我以往的认知中,一个系统一旦正式上线,多半不会轻易的迁移服务器,尤其是那种涉及到多个关联应用,涉及到多台硬件服务器的系统,因为这种迁移将是牵一发而动全身的. 但是,却仍然有这种情况存在,就如我这几天 ...
- SystemVerilog语言简介(一)
1. 接口(Interface) Verilog模块之间的连接是通过模块端口进行的.为了给组成设计的各个模块定义端口,我们必须对期望的硬件设计有一个详细的认识.不幸的是,在设计的早期,我们很难把握设计 ...
- linux之x86裁剪移植---字符界面sdl开发入门
linux下有没有TurboC2.0那样的画点.线.圆的图形函数库,有没有grapihcs.h,或者与之相对应或相似的函数库是什么?有没有DirectX这样的游戏开发库?SDL就是其中之一. SDL( ...
- Java中list.get(index)报错
1.list.get(index)中的index为负值异常 严重:Exception occurred during processing request:-1 java.lang.ArrayInde ...
- ioctl,unlocked_ioctl 处理方法
kernel 2.6.35 及之前的版本中struct file_operations 一共有3个ioctl : ioctl,unlocked_ioctl和compat_ioctl 现在只有unloc ...
- web开发性能优化---分布式篇
1.分布式架构-独立站点开发 模块化结构化开发,实现多资源分站点,数据分库,为后期实现分布式部署做准备,主要分为以下几部分: web站点: 1.web前端站点 2.图片.文件资源站点 3.管理端站点4 ...
- val(),text(),html()的区别
<script type="text/javascript" src="js/jquery-1.8.3.min.js"></script> ...
- 【原】Spring Boot 配置swagger2没有文档解决方案
@Bean public Docket customImplementation(){ return new Docket(DocumentationType.SWAGGER_2) .select() ...
- mybatis快速入门(八)-spring-mybatis动态代理整合
将上一节的代码改造下就好了,不过这一章会加一个basedaomapper.废话不多说直接上代码了. 创建一个BaseDaoMapper.java package cn.my.sm.mapper; /* ...