Python基础2:反射、装饰器、JSON,接口
一、反射
最近接触到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 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,接口的更多相关文章
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- python基础-内置装饰器classmethod和staticmethod
面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...
- python基础5之装饰器
内容概要: 一.装饰器前期知识储备 1.python解释函数代码过程: python解释器从上往下顺序解释代码,碰到函数的定义代码块不会立即执行它,而是将其放在内存中,等到该函数被调用时,才执行其内部 ...
- python基础篇_004_装饰器函数
python装饰器函数 1.装饰器函数引导 功能:计算函数执行时长 import time """ 方式一: 函数首位添加时间,差值就是函数执行时间 缺点:每个函数都要加 ...
- python基础-面向对象(装饰器)
属性: @property @method_name.setter @method_name.deleter 三个标签都是放在方法的上面来使用,且方法名要和后续使用的 变量名字相一 ...
- python基础-5.2装饰器
1.了解装饰器前准备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数,仅指向了函数的地址,为执行 foo() #表示执行foo函数 #### 第二波 # ...
- python基础之内置装饰器
装饰器 简介 功能与格式 内置装饰器 @classmethod @propertry @staticmethod 其它 ---------------------------------------- ...
- 【笔记】Python基础五:装饰器
一,什么是装饰器 本质就是函数,功能是为其他函数添加附加功能 原则: 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 例子: import time def timmer(func): ...
- python 基础篇 12 装饰器进阶
本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...
- python基础-函数之装饰器、迭代器与生成器
1. 函数嵌套 1.1 函数嵌套调用 函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数 def bar(): print("from in the bar.") def f ...
随机推荐
- js 中的bind函数
bind是Function.prototype中内置函数 作用是指定函数作用域 代码参考 http://blog.csdn.net/load_life/article/details/7200381 ...
- Delphi中的“委托”
.NET中有委托(Delegate)的概念,其声明形式如下所示: public delegate void MyDelegate(int aIntParam, string aStringPa ...
- Java并发编程总结2——慎用CAS(转)
一.CAS和synchronized适用场景 1.对于资源竞争较少的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源:而CAS基于硬件实 ...
- python使用easygui写图形界面程序
我 们首先下载一个类库easygui,它是一个Python用于简单开发图形化界面的类库,打开easygui的下载网页 http://sourceforge.net/projects/easygui/? ...
- java线程学习——汉堡销售问题
汉堡店中有一个负责做汉堡的厨师,一个负责销售的营业员,用java线程表示他们的营业过程: 问题原型就是生产者与消费者的问题. 首先定义一个汉堡包箱子类与几个相关的变量类: public class H ...
- GDAL1.9.1 IN VS2008 C#中的编译及使用
下载gdal1.9.1到官网:http://www.gdal.org/ GDAL库的简洁.高效深受开发人员的喜爱,很多开源的GIS软件甚至是商业GIS软件都使用了这个库.GDAL使用C++,在Visu ...
- CentOS, 高速设置ssh无password登录
首先.保证能够ping通 然后运行例如以下命令, master登录slave master上面运行例如以下指令: 2.4 确认本机sshd的配置文件(root) $ vi/etc/ssh/sshd_c ...
- xpage 获取 附件
var db:NotesDatabase=session.getCurrentDatabase(); var doc:NotesDocument=db.getDocumentByUNID('80E21 ...
- 【网络协议】TCP中的四大定时器
前言 对于每个TCP连接,TCP一般要管理4个不同的定时器:重传定时器.坚持定时器.保活定时器.2MSL定时器. 重传定时器 非常明显重传定时器是用来计算TCP报文段的超时重传时间的(至于超时重传时间 ...
- Port 8081 already in use, packager is either not running or not running correctly
运行 react_native 时发生这个错误,解决办法 关掉端口8081对应的进程 1.打开终端,输入命令:lsof -i:8081 2.此时提示: COMMAND PID USER ...