python @修饰符

Python 除了拥有实例方法外,还拥有静态方法和类方法,跟Java相比需要理解这个类方法的含义。

  1. class Foo(object):  
  2.     def test(self)://定义了实例方法  
  3.         print("object")  
  4.     @classmethod  
  5.     def test2(clss)://定义了类方法  
  6.         print("class")  
  7.     @staticmethod  
  8.     def test3()://定义了静态方法  
  9.         print("static")  
  • 实例方法访问方式:
  1. ff.test();//通过实例调用  
  2. Foo.test(ff)//直接通过类的方式调用,但是需要自己传递实例引用  
  • 类方法访问方式:
  1. Foo.test2();  
如果Foo有了子类并且子类覆盖了这个类方法,最终调用会调用子类的方法并传递的是子类的类对象。
  1. class Foo2(Foo):  
  2.     @classmethod  
  3.     def test2(self):  
  4.         print(self)  
  5.         print("foo2 object")  
  6. f2=Foo2()  
  7. print(f2.test2())  
输出结果:
  1. <class '__main__.Foo2'>  
  2. foo2 object  
  • 静态方法调用方式:

 静态方法就跟普通的Java静态方式一样

  1. ff=Foo();<pre name="code" class="python">ff.test3();//使用实例调用  
Foo.test3();//直接静态方式调用


  • 总结

其实通过以上可以看出:

  实例方法,类方法,静态方法都可以通过实例或者类调用,只不过实例方法通过类调用时需要传递实例的引用(python 3可以传递任意对象,其他版本会报错)。

三种方法从不同层次上来对方法进行了描述:实例方法针对的是实例,类方法针对的是类,他们都可以继承和重新定义,而静态方法则不能继承,可以认为是全局函数。




Python中的函数修饰符

首先,什么是函数修饰符?函数修饰符就是对原有函数做一层包装。比如有以下两个函数:

复制代码
  1. def func1():
  2.     print 'I am function func1'

  3. def func2():
  4.     print 'I am function func2'


现在我们想为这两个函数增加一段共同的操作,这时就可以使用函数修饰符。首先我们定义一个修饰函数,先不做任何处理,仅仅打印一条横线:

复制代码
  1. def de( f )
  2.     def call_():
  3.         print '-------------------------------'
  4.         return f()
  5.     return _call_


使用这个修饰符:

复制代码
  1. def de( f ):
  2.     def _call_():
  3.         print '-------------------------------'
  4.         return f()
  5.     return _call

  6. @de
  7. def func1():
  8.     print 'I am function func1'

  9. @de
  10. def func2():
  11.     print 'I am function func2'

  12. if name = '__main__':
  13.     func1()
  14.     func2()


运行结果为:

复制代码
  1. d:\我的文档\桌面>b.py
  2. -------------------------------
  3. I am function func1
  4. -------------------------------
  5. I am function func2

  6. d:\我的文档\桌面>


可以看到,修饰符起作用了。

注意:
1.修饰符等价于包装调用:


  1. @de
  2. def func1:
  3. ----- 等价于 ------
  4. func1 = de( func1 )


2.修饰函数必须返回一个“可调用对象”:


  1. def de( f ):
  2.     def call_():
  3.         return f()
  4.     return _call # 返回的是一个函数体,而非调用_call_()



下一个问题:如果各个被修饰函数有不同的参数,怎么处理呢?例如:


  1. def func1( lst1, lst2 ):
  2.     # 合并两个list,并打印各项
  3.     for item in lst1+lst2:
  4.         print item

  5. def func2( dic ):
  6.     # 循环dict,打印各key-value
  7.     for k, v in dic.items():
  8.         print k, v


这两个函数参数不同,又都没有异常处理,现在我们想增加上,使用修饰符这样处理:


  1. import sys
  2. import traceback

  3. def de( f ):
  4.     def call_( *args, **kwargs ):
  5.         try:
  6.             return f( *args , **kwargs )
  7.         except:
  8.             print 'param type error'
  9.     return _call

  10. @de
  11. def func1( lst1, lst2 ):
  12.     for item in lst1+lst2:
  13.         print item

  14. @de
  15. def func2( dic ):
  16.     for k, v in dic.items():
  17.         print k, v

  18. if name = '__main__':
  19.     func1( [1,2], [3,4] )
  20.     func2( [1,2] )


这里使用了可变参数*args和**kwargs,这样会把所有接收来的参数,原样不动的再转给原函数,是惯用法。
以上程序运行结果:
复制代码

    1. d:\我的文档\桌面>b.py
    2. 1
    3. 2
    4. 3
    5. 4
    6. param type error

    7. d:\我的文档\桌面>


转载请注明: 转载自canX.me

本文链接地址: 一些python

– — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – — – –

最近在试着读OpenStack Nova的源代码。不看别人的代码不知道自己是有多无知啊…

1.协程(Coroutine)

按我现在的理解,协程是比线程还要轻的一种程序并发执行方式。Python用“yield”这个关键字提供了对协程的支持。

看个例子就懂了:

01def foo():
02    for i in range(10):
03        yield i
04        print 'foo: here ' + str(i)
05 
06bar = foo()
07 
08print bar.next()
09print 'main: here'
10print bar.next()
11print bar.next()

例子的输出是:

10
2main: here
3foo: here 0
41
5foo: here 1
62

在协程里,yield起到的是类似return的作用,但是远没有return那么重:没有进程/线程调度,也就不必保存现场,函数只是暂停,过会儿还会从yield处继续执行。而如果yield后面不跟变量,甚至可以把yield看作一个标记,表示这个位置上,函数可以暂停。

上述例子中,代码的执行流程是这个样子的:第一个bar.next()输出i = 0,之后foo()函数暂停,main输出“main: here”,然后每次执行bar.next()输出“foo: here i”,然后返回打印出i。

协程的主要应用场景是服务器端的编程。因为它比线程更轻,所以可以支持更大的并发数。

举个例子,假如在服务器端生成了10000个协程,然后开始运行“调度”函数。当新的连接进入时,“调度”函数给新连接分配一个协程,而当这个协程进行IO时,会暂停让出CPU,“调度”函数再选择其它协程执行。跟进程调度很像,但是协程并没有被“阻塞”,事实上,上述的10000个协程可以是运行在一个线程中的。

OpenStack里面使用了一个叫eventlet的基于协程的网络编程库

主要参考12

2.@修饰符(decorator)

官方文档说修饰符只是一种语法糖(syntactic sugar),简单来说,就是下面两段代码是完全等价的。

1def foo(arg):
2    some code
3foo = bar(foo)
1@bar
2def f(arg):
3    some code

主要参考1

3. @classmethod和@staticmethod

在一个类里面,可以存在三种方法:实例方法、类方法、静态方法,定义方法如下:

01class Foo(object):
02    def instanceFoo(self,x):
03        some code
04 
05    @classmethod
06    def classFoo(cls,x):
07        some code
08 
09    @staticmethod
10    def staticFoo(x):
11        some code

最显然的区别,就是他们接受的参数是不同的。实例方法必须接受一个实例(self),类方法必须接受一个类(cls),静态函数没有要求。

静态方法在python里用途不大,因为class.staticmethod()和module.normalfunction()不管从外观还是从作用都区别不大。而类方法可以用来进行类的实例化:

01>>> class DictSubclass(dict):
02...     def __repr__(self):
03...             return "DictSubclass"
04...
05>>> x = dict.fromkeys('ab')
06>>> print x
07{'a': None, 'b': None}
08>>> y = x.fromkeys('qwe')
09>>> print x,y
10{'a': None, 'b': None} {'q': None, 'e': None, 'w': None}
11>>>

主要参考 12

4.*arg,**arg

这个不是指针,当参数为*arg时,表示接受一个元组;当参数为**arg时,表示接受一个字典

主要参考1

5.继承/多重继承中的参数传递

在继承/多重继承中,参数是逐级向上传递的,最后传递给object(python里一切对象的基类)时,参数应该已经处理完毕。

看个例子:

01class Service(object):
02    def __init__(self, host, binary, topic, manager, report_interval=None,
03             periodic_interval=None, *args, **kwargs):
04        print 'Initializing Service'
05        super(Service, self).__init__(*args, **kwargs)
06 
07        print 'Service: ' + binary, args, kwargs
08 
09class Color(object):
10    def __init__(self, color='red', **kwargs):
11        print 'Initializing Color'
12        self.color = color
13        super(Color, self).__init__(**kwargs)
14 
15        print 'Color: ', kwargs
16 
17class ColoredService(Service, Color):
18    def __init__(self, *args, **kwds):
19        print 'Initializing Colored Service'
20        super(ColoredService, self).__init__(*args, **kwds)
21 
22c = ColoredService('host', 'bin', 'top', 'mgr', 'ivl', color='blue')

输出是:

1Initializing Colored Service
2Initializing Service
3Initializing Color
4Color:  {}
5Service: bin () {'color': 'blue'}

在这个例子里,ColoredService继承了Service和Color,首先初始化ColoredService,然后是Service,此时类Service“吃掉”了传来的大部分参数,只剩下{‘color’: ‘blue’}。然后初始化Color,最后是object。假如传递到object时参数还没有被吃完,python就会报“TypeError: object.__init__() takes no parameters”的错误。

而在多重继承中继承顺序的确定是用了一种叫做C3 Method Resolution Order(MRO)的算法

主要参考12


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值