掌握这些知识,你的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 ...
随机推荐
- asp.mvc中的vue分页实例,分页组件无法重置reload,解决点击查询按钮后,分页不刷新的问题
刚刚接触Vue.js,现在需要做一个查询功能,并且进行服务端分页.主要思路是在页面中注册一个分页组件,然后进行调用.代码如下 1.引用vue.js,具体去网上下载 2.在html的body中添加如下代 ...
- REALTEK 刷机方法 法
REALTEK 是通用板最多的IC 方案之一,什么常说的2025 2270 2023 2033 2525 2545 2660 2280 2662 2670 2672 2674 2661 2668 ...
- vxWorks 命令
1.4.1 任务管理 sp( ) 用缺省参数创建一个任务(priority="100" 返回值为任务ID,或错误)(taskSpawn) sps( ) ...
- 3.2 PCI设备的数据传递
PCI设备的数据传递使用地址译码方式,当一个存储器读写总线事务到达PCI总线时,在这条总线上的所有PCI设备将进行地址译码,如果当前总线事务使用的地址在某个PCI设备的BAR空间中时,该PCI设备将使 ...
- V4L2驱动的移植与应用(二)
二.V4L2的应用 下面简单介绍一下V4L2驱动的应用流程. 1. 视频采集的基本流程 一般的,视频采集都有如下流程: 2. 打开视频设备 在V4L2中,视频设备被看做一个文件.使用open函数打 ...
- pat1011-1020
一开始几道题写到吐血,真的自己现在好弱 1011 水题不说了 #include<bits/stdc++.h> using namespace std; const int N = 105; ...
- .Net Core从命令行读取配置文件
最近在学习博客园腾飞(jesse)的.Net Core视频教程,收益匪浅,在此作推荐 : http://video.jessetalk.cn/ 言归正传,.Net Core应用程序中如何通过命令行读取 ...
- mybatis中动态update中的isNotEmpty和isNotNull标签
一,简介 在iBATIS中isNull用于判断参数是否为Null,isNotNull相反isEmpty判断参数是否为Null或者空,满足其中一个条件则其trueisNotEmpty相反,当参数既不为N ...
- intra调用order
response = orderMessageService.apply(mdpRequest[A1] ); public interface OrderMessageService[A2] { pu ...
- 移动端开发底部元素margin-bottom失效解决办法
一.情景 记得之前开发一个微信端页面时,发现页面底部元素margin-bottom在ios下失效,在安卓内正常...... 1.safari浏览器内页面底部元素设置margin-bottom失效: 2 ...