@staticmethod()虽然定义在类里的函数,但是不受类的影响,就像定义在类外的函数一样。
class cal:
cal_name = 'calculator'
def __init__(self,x,y):
self.x = x
self.y = y
def cal_add(self,x,y):
return self.x + self.y
@staticmethod #静态方法 类或实例均可调用
def cal_add2(x,y):
return x + y
def cal_add3(self,x,y):
return x + y
c1 = cal(10,11) #实例化
print(cal.cal_name)
print(c1.cal_name)
print(c1.cal_add(7,8))
print(cal.cal_add2(6,7.5))
print(c1.cal_add2(6,7.5))
print(c1.cal_add3(7,8))
输出
calculator
calculator
21
13.5
13.5
15
所谓实例化就是c1=cal(10,11),类的constructor赋值。
在大多数应用中,decorator用于修饰函数,那么很显然,装饰器的参数就是函数。
举个例子,我们有100个foo,需要添加每个foo的运行时间。方法一,每个foo改写代码。
def foo1():
print('hello foo1')
start = time.time()
time.sleep(3)
end = time.time()
print('spend %s s'%(end - start))
def foo2():
print('hello foo2')
start = time.time()
time.sleep(3)
end = time.time()
print('spend %s s'%(end - start))
foo1()
foo2()
输出
hello foo1
spend 3.00324392319 s
hello foo2
spend 3.00317907333 s
方法二,写一个公用的函数调用100个foo,该函数参数即函数,即函数的函数。那么原来的foo代码就不用改写了。
def show_time(func):
start_time=time.time()
func()
end_time=time.time()
print('spend %s'%(end_time-start_time))
def foo():
print('hello foo2')
time.sleep(3)
show_time(foo)
输出
hello foo2
spend 3.00352692604
方法三,装饰器修饰100个foo,那么装饰器函数不但要是函数的函数,还必须是嵌套函数。
def show_time(func):
def inner():
start = time.time()
func()
end = time.time()
print('spend %s'%(end - start))
return inner
@show_time
def foo():
print('hello foo')
time.sleep(1)
@show_time
def foo2():
print('hello foo2')
time.sleep(2)
foo()
foo2()
输出
hello foo
spend 1.00129795074
hello foo2
spend 2.00224804878
装饰过的函数,如果执行函数()调用,那么编译执行时是执行内嵌的完整函数,否者会出现TypeError: 'NoneType' object is not callable。如果仅仅调用被装饰函数名(不带括号),那么装饰器函数不需要内嵌另一个函数。python的函数名是指针。
下面看一个编译先后顺序的例子。
def bread(func) :
def wrapper() :
print "</''' '''\>"
func()
print "<\______/>"
return wrapper
def ingredients(func) :
def wrapper() :
print "#tomatoes#"
func()
print "~salad~"
return wrapper
@bread
@ingredients
def sandwich(food="--ham--") :
print food
sandwich()
输出
</''' '''\>
#tomatoes#
--ham--
~salad~
<\______/>
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
最后看看@property用法,一个事物的性质,比如一个半径等于r的圆是一个object,那么该圆的面积和周长和半径r是相关的,那么该圆的面积函数和周长函数最适合用@property修饰,构造该对象只需指定半径r。
import math
class Circle:
def __init__(self,radius):
self.radius=radius
@property
def area(self):
return math.pi * self.radius**2
@property
def perimeter(self):
return 2*math.pi*self.radius
c=Circle(10)
print(c.radius)
print(c.area)
print(c.perimeter)
输出
10
314.159265359
62.8318530718