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()
# 运行结果
enter
doing something
exit
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 enter
in with
in exit
另外python库中还有一个模块contextlib,使你不用构造含有enter, exit的类就可以使用with:
from contextlib import contextmanager
from __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 closing
import 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')
# 运行结果
Parent
Child
HelloWorld from Parent
Child bar fuction
I'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__) #(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
#执行结果
D
B
C
A
3、python对象的自省机制
检查某些事物以确定它是什么、它知道什么以及它能做什么,运行时能够获得对象的类型。
type() :一个参数返回对象类型, 三个参数,返回新的类型对象
dir() : 用于返回参数的属性和方法列表
getattr() : 用于返回一个对象属性值
hasattr() : 用于判断对象是否包含对应的属性
isinstance() : 用于判断一个对象是否是一个已知的类型
# class type(name, bases, dict)
# 参数
# name -- 类的名称。
# bases -- 基类的元组。
# dict -- 字典,类内定义的命名空间变量。
# 一个参数实例
>>> type(1)
<type 'int'>
>>> type('runoob')
<type 'str'>
>>> type([2])
<type 'list'>
>>> type({0:'zero'})
<type 'dict'>
>>> x = 1
>>> type( x ) == int # 判断类型是否相等
True
# 三个参数
>>> class X(object):
... a = 1
...
>>> X = type('X', (object,), dict(a=1)) # 产生一个新的类型 X
>>> X
<class '__main__.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__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
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']</pre>
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):
pass
class B(D):
pass
class A(B,C):
pass
#顺序:A,B,C,D #__mro__,类的属性查找顺序
print(A.__mro__) #(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)</pre>
image
class E:
pass
class C(E):
pass
class B(D):
pass
class A(B,C):
pass
#顺序:A,B,D,C,E #__mro__,类的属性查找顺序
print(A.__mro__) #(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)</pre>
6、类变量和实例变量
python的类变量和实例变量,顾名思义,类变量是指跟类的变量,而实例变量,指跟类的具体实例相关联的变量
class A:
#类变量
bb = 11
def __init__(self,x,y): #实例变量
self.x = x
self.y = y
a = A(2,3)
A.bb = 111111
print(a.x,a.y,a.bb) # 2 3 111111
print(A.bb) # 111111
a.bb = 2222 #实际上会在实例对象a里面新建一个属性bb
print(a.bb) # 2222
print(A.bb) # 111111</pre>
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:
pass
class B(A):
pass
b = B()
#判断b是不是B的类型
print(isinstance(b,B)) #True
# b是不是A的类型呢,也是的
#因为B继承A,isinstance内部会去检查继承链
print(isinstance(b,A)) #True
print(type(b) is B) #True
#b指向了B()对象,虽然A是B的父类,但是A是另外一个对象,它们的id是不相等的
print(type(b) is A) #False
网友评论