python 类_Python之深入类和对象

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、类和实例属性的查找顺序
7410cea6602923ad37f105126ddc3b76.png

image

class C(D):    passclass B(D):     passclass A(B,C):      pass#顺序:A,B,C,D #__mro__,类的属性查找顺序print(A.__mro__)      #(, , , , )
ad4396f5a24ffeb0542901c161af6cce.png

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值