python水平_掌握这些知识,你的python水平能更上一层楼(续)

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

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

defcountcalls(func):

count=0def wrapper(*args, **kwargs):

count+= 1

print('num of calls: {}'.format(count))return func(*args, **kwargs)returnwrapper

@countcallsdeffoo(x):print (x+1)

foo(1)

运行时会发现:

UnboundLocalError: local variable 'count' referenced before assignment

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

python3的解决方案:

nonlocal count

count += 1

python2的解决方案:

defcountcalls(func):def wrapper(*args, **kwargs):

wrapper.count+= 1

print('num of calls: {}'.format(wrapper.count))return func(*args, **kwargs)

wrapper.count=0return wrapper

基于class的decorator

classPrintLog:def __init__(self, func):

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

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

classPrintLog:def __init__(self, func):

self.func=funcdef __call__(self, *args, **kwargs):print ('CALLING: {}'.format(self.func.__name__))return self.func(*args, **kwargs)defprintlog(func):def wrapper(*args, **kwargs):print("CALLING:" + func.__name__)return func(*args, **kwargs)returnwrapper

@printlogdeff(n):return n+2@PrintLogdeff_class(n):return n+2

CALLING: f

5

CALLING: f_class

5

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

magic methods

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

classAngle: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 +bprint (c.value)

135

常用方法如下:

数学运算__add__ a +b__sub__ a -b__mul__ a *b__truediv__ a/b(浮点除)__mod__ a %b__pow__ a **b

位运算__lshift__ 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

举个例子:

classMoney(object):def __init__(self, dollar, cent):

self.dollars=dollar

self.cents=centdef __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) % 100dollars= self.dollars + other.dollars + (self.cents + other.cents)/100

returnMoney(dollars, cents)def __sub__(self, other):if self.cents

cents= 100 + self.cents -other.cents

dollars= self.dollars - other.dollars - 1

else:

cents= self.cents -other.cents

dollars= self.dollars -other.dollarsreturnMoney(dollars, cents)def __mul__(self, other):

cents= (self.cents * other) % 100dollars= self.dollars * other + (self.cents * other) / 100

returnMoney(dollars, cents)def __eq__(self, other):return self.dollars == other.dollars and self.cents ==other.centsdef __ge__(self, other):return self.dollars >= other.dollars and self.cents >=other.centsdef __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

classUniqueList:def __init__(self, items):

self.items=[]for item initems:

self.append(item)defappend(self, item):if item not inself.items:

self.items.append(item)def __getitem__(self, index):returnself.items[index]

ul= UniqueList([2,2,2,3,3,3,4,4,4])printul[0]print ul[1]print ul[2]

2

3

4

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

classMultiDict:def __init__(self):

self.data={}definsert(self, key, value):if key not inself.data:

self.data[key]=[]

self.data[key].append(value)defget_values(self, key):returnself.data[key]defget(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 inul:print i

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

Iterator的另一种实现是:

def __iter__(self):returnselfdef __next__(self):

...raiseStopIterationreturn ...

可见__getitem__显得更简洁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值