一、反射

  最近接触到python的反射机制,遂记录下来已巩固。但是,笔者也是粗略的使用了__import__, getattr()函数而已。目前,笔者的理解是,反射可以使用户通过自定义输入来导入响应的module、class等。下面以一个例子说明。

  文件目录如下,

    

  reflection文件夹下有Car module,现在main.py下通过反射机制导入Car module.

  Car.py源码如下:

 class Car(object):
def __init__(self, name, color, tire, engine):
self.name = name
self.color = color
self.tire = tire
self.__engine = engine
def run(self):
print '{} runs at the street.'.format(self.name)
def stop(self):
print '{} stops running.'.format(self.name) class Audi(Car):
def __init__(self, name, color, tire, engine):
super(Audi, self).__init__(name, color, tire, engine)

  main.py源码如下: 

 #from reflection import Car
#from reflection.Car import * string = raw_input('Please input import module(xxx/xxx):')
path = string.split('/')
namespace = __import__('reflection.'+path[0])
module = getattr(namespace, path[1])
Audi = getattr(module, 'Audi')
print namespace
print module
print Audi my_audi = Audi('A7', 'red', 4, 'wolun')
my_audi.run()

  首先,main中1,2行是一般的导入模式。然后,让用户输入需导入的模块(字符串),通过__import__函数导入module,通过getattr()函数得到module的class,方法等。运行main.py,输入Car/Car,意在导入module Car。运行结果如下,

 Please input import module(xxx/xxx):Car/Car
<module 'reflection' from 'f:\Python\Wing\reflection\reflection\__init__.pyc'> #print namespace
<module 'reflection.Car' from 'f:\Python\Wing\reflection\reflection\Car.py'> #print module
<class 'reflection.Car.Audi'>                              #print Audi
A7 runs at the street.

  输出结果很清楚的显示了__import__,getattr()的功能。对于反射机制,笔者也是简单的了解到这些。

二、super

  关于super,首先要注意的是,super并非是一个函数,而是一个类(PySuper_Type)。在bltinmodule.c中有这么一条语句:

 SETBUILTIN("super",  &PySuper_Type);

  然后,在python documention中有这样一段描述:

 Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have  been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

 The __mro__ attribute of the type lists the method resolution search order used by both getattr() and super(). The attribute is dynamic and can c hange whenever the inheritance hierarchy is updated.

 If the second argument is omitted, the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true (this is useful for classmethods).

  下面,以一个例子来简单说明super是如何实现多继承的。

 class A(object):
def __init__(self):
print "enter A"
super(A, self).__init__() # new
print "leave A" class B(object):
def __init__(self):
print "enter B"
super(B, self).__init__() # new
print "leave B" class C(A):
def __init__(self):
print "enter C"
super(C, self).__init__()
print "leave C" class D(A):
def __init__(self):
print "enter D"
super(D, self).__init__()
print "leave D"
class E(B, C):
def __init__(self):
print "enter E"
super(E, self).__init__() # change
print "leave E" class F(E, D):
def __init__(self):
print "enter F"
super(F, self).__init__() # change
print "leave F" >>> f = F() enter F
enter E
enter B
enter C
enter D
enter A
leave A
leave D
leave C
leave B
leave E
leave F

  可以清楚的看到,F的初始化不仅完成了所有的父类的调用,而且保证了每一个父类的初始化函数只调用一次。关于深度探索super的用法,下面两篇文章值得推荐。

  http://www.jb51.net/article/66912.htm

  https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

三、装饰器

  1、对带参数的函数进行装饰

 def deco(func):
def _deco(a, b):
print("before myfunc() called.")
ret = func(a, b)
print(" after myfunc() called. result: %s" % ret)
return ret
return _deco @deco
def myfunc(a, b):
print(" myfunc(%s,%s) called." % (a, b))
return a + b myfunc(1, 2)
myfunc(3, 4)

  2、对参数数量不确定的函数进行装饰  

 def deco(func):
def _deco(*args, **kwargs):
print("before %s called." % func.__name__)
ret = func(*args, **kwargs)
print(" after %s called. result: %s" % (func.__name__, ret))
return ret
return _deco @deco
def myfunc(a, b):
print(" myfunc(%s,%s) called." % (a, b))
return a+b @deco
def myfunc2(a, b, c):
print(" myfunc2(%s,%s,%s) called." % (a, b, c))
return a+b+c myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)

  3、装饰器带参数

 def deco(arg):
def _deco(func):
def __deco():
print "before {} called [{}]." .format(func.__name__, arg)
func()
print " after {} called [{}].".format(func.__name__, arg)
return __deco
return _deco @deco("module1")
def myfunc():
print " myfunc() called." @deco("module2")
def myfunc2():
print " myfunc2() called." myfunc()
myfunc2()

  4、装饰器带 类 参数

 #! coding = utf-8
class locker:
def __init__(self):
print "locker.__init__() should be not called." @staticmethod
def acquire():
print "locker.acquire() called.(这是静态方法)" @staticmethod
def release():
print " locker.release() called.(不需要对象实例)" def deco(cls):
'''''cls 必须实现acquire和release静态方法'''
def _deco(func):
def __deco():
print "before {} called [{}].".format(func.__name__, cls)
cls.acquire()
try:
return func()
finally:
cls.release()
return __deco
return _deco @deco(locker)
def myfunc():
print " myfunc() called." myfunc()

  值得注意的是,类虽然作为了装饰器的参数,但是没有instance,那么__init__()方法不会被执行。

  5、装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器 

 '''
mylocker.py ,prepare for the deco.py
'''
class mylocker:
def __init__(self):
print "mylocker.__init__() called." @staticmethod
def acquire():
print "mylocker.acquire() called." @staticmethod
def unlock():
print " mylocker.unlock() called." class lockerex(mylocker):
@staticmethod
def acquire():
print "lockerex.acquire() called." @staticmethod
def unlock():
print " lockerex.unlock() called." def lockhelper(cls):
'''cls must instance 'acquire' and 'release' static methods'''
def _deco(func):
def __deco2(*args, **kwargs):
print "before {} called." .format(func.__name__)
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return __deco2
return _deco
 '''
deco.py
装饰器带类参数,并分拆公共类到其他py文件(mylocker.py)中
同时演示了对一个函数应用多个装饰器
''' from mylocker import * class example:
@lockhelper(mylocker)
def myfunc(self):
print " myfunc() called." @lockhelper(mylocker)
@lockhelper(lockerex)
def myfunc2(self, a, b):
print " myfunc2() called."
return a + b if __name__=="__main__":
a = example()
#a.myfunc()
#print '---------------------------------------------------------'
#print a.myfunc()
#print '---------------------------------------------------------'
#print a.myfunc2(1, 2)
#print '---------------------------------------------------------'
print a.myfunc2(3, 4)

  不过,注意到这段程序的输出: 

before __deco2 called.
mylocker.acquire() called.
before myfunc2 called.
lockerex.acquire() called.
myfunc2() called.
lockerex.unlock() called.
mylocker.unlock() called.
7

  为什么有“before __deco2__ called”??这段输出给我的感觉就是,mylocker装饰了__deco2(),而lockerex装饰了myfunc2().是这样理解的么??

四、pickle & json

  pickle & json 都可以存储数据到硬盘,供程序交互。不过,pickle是python特有的,json可以为不同语言所共有。所以,json用得更普遍。下面这个例子分别用pickle,json 来dump,load  & dumps,loads 数据。

 import pickle
import json mydict = {'name': 'python', 'age': 27, 'height': 178, 'weight': 140}
#pickle dumps, loads
res = pickle.dumps(mydict)
print res
loadres = pickle.loads(res)
print loadres
print '----------------------------------------------------------'
#pickle dump,load
pickle.dump(mydict, open('C:\Users\Administrator\Desktop\jason.txt', mode='w'))
loadres = pickle.load(open('C:\Users\Administrator\Desktop\jason.txt', mode='r'))
print loadres
print '----------------------------------------------------------'
#json dumps,loads
jsonres = json.dumps(mydict, skipkeys=False, ensure_ascii=True,
check_circular=True, allow_nan=True,
cls=None, indent=None,
separators=None, encoding='utf-8',
default=None)
print jsonres
load_json_res = json.loads(jsonres, encoding=None, cls=None, object_hook=None,
parse_float=None,
parse_int=None,
parse_constant=None,
object_pairs_hook=None)
print load_json_res
print '----------------------------------------------------------'
#json dump,load
json.dump(mydict, open('C:\Users\Administrator\Desktop\jason.txt', mode='w'), skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
encoding='utf-8', default=None)
fileres = json.load(open('C:\Users\Administrator\Desktop\jason.txt', 'r'), encoding=None, cls=None, object_hook=None,
parse_float=None, parse_int=None,
parse_constant=None,
object_pairs_hook=None)
print fileres

五、接口

  在类的定义中用abc.ABCMeta作为metaclass写自己的抽象基类。示例代码如下: 

 from abc import ABCMeta, abstractmethod
class interface(object): #这里填不填object????
__metaclass__ = ABCMeta @abstractmethod
def show(self):
pass class Fighting(interface):
def __init__(self, message):
self.message = message def show(self):
Fighting.mystatic()
print 'overwrite the function of show in interface'
def __str__(self):
return self.message
@staticmethod
def mystatic():
print 'call static method in class' class MyException(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return self.message try:
input_message = raw_input('Please input the fighting message:')
f = Fighting(input_message)
print f
f.show()
string = f.__str__()
if 'Any questions?' == string:
raise MyException("No thanks!")
else:
print 'You are a good man.'
except MyException, e :
print e
finally:
print 'finally must be called.'

  更多关于abc module,在python documention中讲解的很清楚。abc.ABCMeta,abc.abstractmethod,abc.abstractproperty等...

六、property

  property,笔者理解为class的一个特性吧。先以一段示例程序,看看property是如何工作的。

 class Car(object):

     company = 'aodi'
__engine = 'wolunzengya'
def __init__(self, name, color, style):
self.name = name
self.color = color
self.__style = style
def start(self):
print self.name + ' run the road.'
def stop(self):
print self.name + ' stop the engine.' @staticmethod
def engine():
print 'we all have engines.'
@property
def Car_company(self):
print 'Our company is {},engine is {} '.format(Car.company, Car.__engine)
def __changeEngine():
Car.__engine = 'shuangwolunzengya' @property
def style(self):
return self.__style
@style.setter
def style(self, value):
self.__style = value @property
def haha(self):
return self.color def __call__(self):
print '{}\'s call method is called.'.format(self.name) aodi_a6 = Car('a6', 'white', 'tesila') print aodi_a6.style
aodi_a6.style = 'bujiadi'
print aodi_a6.style
print print aodi_a6.haha #notian that the function 'haha' has no parathinese'()'
aodi_a6.haha = 'red' #tips: 新式类不可以在这里赋值,旧式类可以
print aodi_a6.haha aodi_a6()

  在上述程序中,如果Car(object)为新式类,将会产生AttributeError: can't set attribute.产生这个错误的语句在:aodi_a6.haha = 'red'。。如果使用新式类,就要使用@XXX.setter 标记函数,达到赋值效果。如程序中的style方法:

@property
def style(self):
return self.__style
@style.setter
def style(self, value):
self.__style = value

  再提一下,调用@property修饰的方法,不加()。

  静下心来博客,也理清了自己的思路,坚持~

  

  

Python基础2:反射、装饰器、JSON,接口的更多相关文章

  1. Python基础-迭代器&生成器&装饰器

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...

  2. python基础-内置装饰器classmethod和staticmethod

    面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...

  3. python基础5之装饰器

    内容概要: 一.装饰器前期知识储备 1.python解释函数代码过程: python解释器从上往下顺序解释代码,碰到函数的定义代码块不会立即执行它,而是将其放在内存中,等到该函数被调用时,才执行其内部 ...

  4. python基础篇_004_装饰器函数

    python装饰器函数 1.装饰器函数引导 功能:计算函数执行时长 import time """ 方式一: 函数首位添加时间,差值就是函数执行时间 缺点:每个函数都要加 ...

  5. python基础-面向对象(装饰器)

    属性:   @property   @method_name.setter   @method_name.deleter   三个标签都是放在方法的上面来使用,且方法名要和后续使用的   变量名字相一 ...

  6. python基础-5.2装饰器

    1.了解装饰器前准备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数,仅指向了函数的地址,为执行 foo() #表示执行foo函数 #### 第二波 # ...

  7. python基础之内置装饰器

    装饰器 简介 功能与格式 内置装饰器 @classmethod @propertry @staticmethod 其它 ---------------------------------------- ...

  8. 【笔记】Python基础五:装饰器

    一,什么是装饰器 本质就是函数,功能是为其他函数添加附加功能 原则: 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 例子: import time def timmer(func): ...

  9. python 基础篇 12 装饰器进阶

    本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...

  10. python基础-函数之装饰器、迭代器与生成器

    1. 函数嵌套 1.1 函数嵌套调用 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数 def bar(): print("from in the bar.") def f ...

随机推荐

  1. 第一个VC++ win32程序 绘制简单图形

    创建一个VC++ win32 打开VS 新工程类型中选择Win32----Win32 Project  自己取个名字(假如叫做My1stWin) 一路next 系统会自动生成好最基本的代码  然后我们 ...

  2. Bootstrap dropdown 使用

    同样是2种方式 参考http://www.bootcss.com/javascript.html#dropdowns JS方式调用 http://www.w3resource.com/twitter- ...

  3. 一个高效过滤非UTF8字符的C函数(也可用来判断是否utf8)

    /* UTF-8 valid format list: 0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxx 10xxxxxx ...

  4. C++模板:欧拉函数

    单个欧拉函数 int eular(int n){ int ret=1,i; for(i=2;i*i<=n;i++) if(n%i==0){ n/=i,ret*=i-1; while(n%i==0 ...

  5. poj 1144 Network(割点)

    题目链接: http://poj.org/problem?id=1144 思路分析:该问题要求求出无向联通图中的割点数目,使用Tarjan算法即可求出无向联通图中的所有的割点,算法复杂度为O(|V| ...

  6. Oracle游标-循环查询表中数据(表名),并执行

    Oralce 表中存有一个字段,该字段存储表名,要把该表中的所有表名查询出来(即表名结果集),且执行结果集from 表名结果集: declare v_ccount ); --定义一个游标变量 curs ...

  7. eclipse打war包

    链接地址:http://jingyan.baidu.com/article/c910274be14164cd361d2ddc.html 一个程序要想放到服务器容器中很多人想到了打一个war包放到tom ...

  8. STL之map和multimap(关联容器)

    map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响.自动建立Key - value的对应,对于迭代器来说,可以修改实值,而不能修改key. ...

  9. 移除Strorefront站点footer上的Storefront Design By WooThemes字样

    进入wp-content\themes\storefront\inc\structure\footer.php, 注释掉代码: if ( ! function_exists( 'storefront_ ...

  10. Xamarin.Android开发实践(三)

    原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...