1、with语句(上下文管理器)
Python 提供了 with 语法用于简化资源操作的后续清除操作,是 try/finally 的替代方法,实现原理建立在上下文管理器之上。
#上下文管理器class Sample: def __enter__(self): print('enter') #获取资源 return self def __exit__(self, exc_type, exc_val, exc_tb): #释放资源 print('exit') def do_something(self): print('doing something')#会自动执行enter和exit方法with Sample() as sample: sample.do_something()# 运行结果enterdoing somethingexit
python中with可以明显改进代码友好度,比如:
with open('a.txt') as f: print f.readlines()
为了我们自己的类也可以使用with, 只要给这个类增加两个函数enter, exit即可:
class A: def __enter__(self): print 'in enter' def __exit__(self, e_t, e_v, t_b): print 'in exit' with A() as a: print 'in with'# 运行结果in enterin within exit
另外python库中还有一个模块contextlib,使你不用构造含有enter, exit的类就可以使用with:
from contextlib import contextmanagerfrom __future__ import with_statement @contextmanager def context(): print 'entering the zone' try: yield except Exception, e: print 'with an error %s'%e raise e else: print 'with no error' with context(): print '----in context call------'# 运行结果entering the zone----in context call------with no error
使用的最多的就是这个contextmanager, 另外还有一个closing 用处不大
from contextlib import closingimport urllib with closing(urllib.urlopen('http://www.python.org')) as page: for line in page: print line
2、super函数
2.1、super() 函数是用于调用父类(超类)的一个方法
#!/usr/bin/python# -*- coding: UTF-8 -*- class FooParent(object): def __init__(self): self.parent = 'I'm the parent.' print ('Parent') def bar(self,message): print ("%s from Parent" % message) class FooChild(FooParent): def __init__(self): # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象 super(FooChild,self).__init__() print ('Child') def bar(self,message): super(FooChild, self).bar(message) print ('Child bar fuction') print (self.parent) if __name__ == '__main__': fooChild = FooChild() fooChild.bar('HelloWorld')# 运行结果ParentChildHelloWorld from ParentChild bar fuctionI'm the parent.
2.2、使用 super() 可以很好地避免构造函数被调用两次。
class A(): def __init__(self): print('enter A') print('leave A')class B(A): def __init__(self): print('enter B') super().__init__() print('leave B')class C(A): def __init__(self): print('enter C') super().__init__() print('leave C')class D(B, C): def __init__(self): print('enter D') super().__init__() print('leave D')d = D()print(D.__mro__) #(, , , , ) #执行结果DBCA
3、python对象的自省机制
检查某些事物以确定它是什么、它知道什么以及它能做什么,运行时能够获得对象的类型。
type() :一个参数返回对象类型, 三个参数,返回新的类型对象 dir() : 用于返回参数的属性和方法列表 getattr() : 用于返回一个对象属性值 hasattr() : 用于判断对象是否包含对应的属性 isinstance() : 用于判断一个对象是否是一个已知的类型
# class type(name, bases, dict)# 参数# name -- 类的名称。# bases -- 基类的元组。# dict -- 字典,类内定义的命名空间变量。# 一个参数实例>>> type(1)>>> type('runoob')>>> type([2])>>> type({0:'zero'})>>> x = 1 >>> type( x ) == int # 判断类型是否相等True # 三个参数>>> class X(object):... a = 1...>>> X = type('X', (object,), dict(a=1)) # 产生一个新的类型 X>>> X
# type() 和isinstance()区别1. type() 不会认为子类是一种父类类型,不考虑继承关系。2. isinstance() 会认为子类是一种父类类型,考虑继承关系。# 如果要判断两个类型是否相同推荐使用 isinstance()。示例: class A: pass class B(A): pass isinstance(A(), A) # returns True type(A()) == A # returns True isinstance(B(), A) # returns True type(B()) == A # returns False
class Student(Person): def __init__(self,school_name): self.school_name = school_name if __name__ == "__main__": user = Student('仙剑') #通过 __dict__ 查询有哪些属性 print(user.__dict__) #{'school_name': '仙剑'} print(Person.__dict__) #{'__module__': '__main__', '__doc__': '人类', 'name': 'user', '__dict__': , '__weakref__': } print(Person.__doc__) #人类 #可以添加属性 user.__dict__['school_addr'] = '北京' print(user.school_addr) #北京 #dir也可以查看属性,比__dict__功能更强大 print(dir(user)) #['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'school_addr', 'school_name']
4、类方法,静态方法,和实例方法
class Date(): #构造函数 def __init__(self,year,month,day): self.year = year self.month = month self.day = day #实例方法 def tomorrow(self): self.day += 1 # 静态方法不用写self @staticmethod def parse_from_string(date_str): year, month, day = tuple(date_str.split("-")) # 静态方法不好的地方是采用硬编码,如果用类方法的话就不会了 return Date(int(year), int(month), int(day)) #类方法 @classmethod def from_string(cls, date_str): year, month, day = tuple(date_str.split("-")) # cls:传进来的类,而不是像静态方法把类写死了 return cls(int(year), int(month), int(day)) def __str__(self): return '%s/%s/%s'%(self.year,self.month,self.day)if __name__ == "__main__": new_day = Date(2018,5,9) #实例方法 new_day.tomorrow() print(new_day) #2018/5/10 #静态方法 date_str = '2018-05-09' new_day = Date.parse_from_string(date_str) print(new_day) #2018/5/9 # 类方法 date_str = '2018-05-09' new_day = Date.from_string(date_str) print(new_day) # 2018/5/9
5、类和实例属性的查找顺序
image
class C(D): passclass B(D): passclass A(B,C): pass#顺序:A,B,C,D #__mro__,类的属性查找顺序print(A.__mro__) #(, , , , )
image
class E: passclass C(E): passclass B(D): passclass A(B,C): pass#顺序:A,B,D,C,E #__mro__,类的属性查找顺序print(A.__mro__) #(, , , , , )
6、类变量和实例变量
python的类变量和实例变量,顾名思义,类变量是指跟类的变量,而实例变量,指跟类的具体实例相关联的变量
class A: #类变量 bb = 11 def __init__(self,x,y): #实例变量 self.x = x self.y = ya = A(2,3)A.bb = 111111print(a.x,a.y,a.bb) # 2 3 111111print(A.bb) # 111111 a.bb = 2222 #实际上会在实例对象a里面新建一个属性bbprint(a.bb) # 2222print(A.bb) # 111111
7、使用isinstance而不是type
7.1、语法:
isinstance(object, classinfo)
其中,object 是变量,classinfo 是类型即 (tuple,dict,int,float,list,bool等) 和 class类
若参数 object 是 classinfo 类的实例,或者 object 是 classinfo 类的子类的一个实例, 返回 True。 若 object 不是一个给定类型的的对象, 则返回结果总是False。
若 classinfo 不是一种数据类型或者由数据类型构成的元组,将引发一个 TypeError 异常。
7.2、isinstance简单用法
>>> isinstance(1,int)True>>> >>> isinstance('1',str)True>>> >>> isinstance(1,list)False
7.3、type()与isinstance()的区别:
- 共同点:两者都可以判断对象类型
- 不同点:对于一个 class 类的子类对象类型判断,type就不行了,而 isinstance 可以。
class A: passclass B(A): passb = B()#判断b是不是B的类型print(isinstance(b,B)) #True# b是不是A的类型呢,也是的#因为B继承A,isinstance内部会去检查继承链print(isinstance(b,A)) #Trueprint(type(b) is B) #True#b指向了B()对象,虽然A是B的父类,但是A是另外一个对象,它们的id是不相等的print(type(b) is A) #False