python09-面向对象(二) & 异常

面向对象

  • 回顾:

    • 反射:以字符串的形式去某个对象(模块,类,对象)操作它的成员(python中,一切皆对象)
    # 从模块中获取属性
    module = __import__('commons') # 引入commons模块
    if __name__ == '__main__':
        if hasattr(module, 'f1'):
            # print('ok')
            f1 = getattr(module, 'f1')
            ret = f1()
            print('ret =', ret)
    
    # 从类中获取属性
    class Cat:
        desc = 'YHH'
        def __init__(self, name):
            self.name = name
    
        def show(self):
            print(self.name)
    
    show = getattr(Cat, 'show')
    show(Cat('yhh'))
    
    # 从对象中获取属性
    cat = Cat('yhh')
    show = getattr(cat, 'show')
    show()
    
    • 多继承面试题:
    # 继承关系:
    # A(ooo) --> D
    # B(ooo) --> C(xxx,ooo) --> D
    class D(A,C):
        pass
    dog = D() # 创建D实例
    dog.xxx() # 调用xxx方法,只有C有,调用C的
    # 在xxx方法内部调用ooo方法,虽然C也有ooo方法
    # 但是函数内部调用方式为:self.ooo()
    # 根据继承的调用顺序,虽有调用的是A的ooo方法
    # 看别人的代码时,惊颤遇到这个问题--方法由谁发起的就由谁开始找
    
    • 继承中调用构造方法
      • 创建对象时会调用对象的__init__方法
      • 如果对象没有__init__方法,回去调用父类的构造方法
    class Animal:
        def __init__(self):
            print('Animal')
    class Cat(Animal):
        def __init__(self):
            print('Cat')
    cat = Cat() # Cat
    # =====================
    class Animal:
        def __init__(self):
            print('Animal')
    
    class Cat(Animal):
        # def __init__(self):
        #     print('Cat')
        pass
    
    cat = Cat() # Animal
    
    • 调用父类的构造方法
      • 调用父类的构造方法有两种方式:
    # 一:第一个参数为当前类,第二个参数为self
    # 表示找到Cat的父类并执行构造方法
    class Animal:
        def __init__(self):
            print('Animal')
    
    class Cat(Animal):
        def __init__(self):
            print('Cat')
            super(Cat, self).__init__()
    
    cat = Cat() # Cat Animal
    # 二:主动去调用父类的构造方法
    class Animal:
        def __init__(self):
            print('Animal')
    
    class Cat(Animal):
        def __init__(self):
            print('Cat')
            Animal.__init__(self)
    cat = Cat() # Cat Animal
    
  • 成员:

    • 反射:
      • 通过类-对象指针也能找到类中的方法
    class Cat():
        def __init__(self, name):
            self.name = name
        def show(self):
            print(self.name)
    
    cat = Cat('yhh')
    ret = hasattr(Cat, 'show') # 类中的方法
    print(ret) # True
    ret = hasattr(cat, 'name') # 对象的属性
    print(ret) # True
    ret = hasattr(cat, 'show') # 对象的方法
    print(ret) # True
    
    • 手动实现从导入模块到创建对象再获取对象属性的反射
    module = __import__('commons', fromlist=True)
    class_name = getattr(module, 'Cat')
    cat = class_name('yhh')
    name = getattr(cat, 'name')
    print(name) # yhh
    method = getattr(cat, 'show')
    method()
    
    • 静态字段:静态字段存在类中

      • 如果一个类中所有的对象都用共同的字段且想通过,可将此字段设置为静态字段
      • 在类中存在的字段为静态字段,在对象中存在的字段为普通字段
      class Province:
          country = 'China' # 静态字段
      
    • 类的成员:普通字段,普通方法,静态字段,静态方法,类方法,特性

      • 约定俗成:普通字段,普通方法由对象访问,静态字段,静态方法,类方法由类访问
      • 通过类访问普通方法需要参数需要传入对象
    • 静态方法

    class Cat:
        @staticmethod
        def show():
            pass
    
    • 类方法
      • 类方法其实相当于静态方法的另一种形式,只是调用时python自动将类名传给方法
    class Cat:
        @classmethod
        def show(cls):
            print(cls)
    
    Cat.show()
    
    • 特性(属性)

      • 执行方法一般为对象名.方法名()来调用,如果在定义方法的时候加上@property,那么调用该方法是不需要加上括号(前提是该方法不需要参数)
      • 当方法名和字段名相同,写在后面的会覆盖前面的,一般不会这么写
      • 作用:把方法伪造成字段来操作(比较鸡肋)
      class Cat:
          def __init__(self, name):
              self.name = name
          @property
          def show(self):
              print(self.name)
      
      cat = Cat('yhh')
      cat.show
      
      cat.name # 获取字段
      cat.name = 'newName' # 修改字段
      cat.show    # 通过特性,以字段的形式调用函数
      cat.show = 'haha'   # 报错
      # 如果想要不报错,则修改代码
      class Cat:
      def __init__(self, name):
          self.name = name
      @property
      def show(self):
          print(self.name)
      @show.setter
      def show(self,arg):
          self.name = arg
      
      cat = Cat('yhh')
      cat.show
      cat.show = 'catName'
      cat.show
      # 定义一个和@property方法名一样的方法,方法加上@方法名.setter就可以使得方法可以像修改属性一样传递参数
      
  • 修饰符:

    • 在方法或者字段前加上__表示私有
    • 私有的方法和属性不能被继承,只有自己能够访问
    • 私有也可以获取:
      • python中有个特殊的方法,私有的实行和方法也可以获取,一般不会这么用
    class Cat:
        __xo = 'xo'
        def __show(self):
            print('show')
        def pub(self):
            self.__show()
    cat = Cat()
    print(cat._Cat__xo)
    # 对象._类名__属性名或方法
    
  • 特殊方法:

    • __init__:构造方法,创建对象的时候调用
    • __del__:解析器销毁对象的时候调用
    • __call__:当调用对象名()的时候调用
      • Django,web框架的源码用到
    class Cat:
        def __init__(self):
            print('创建对象的时候调用')
        def __call__(self, *args, **kwargs):
            print('对象名()调用')
    
    cat = Cat() # 调用构造方法
    cat() # 调用call方法
    
    • __setitem__,__getitem__,__delitem__
      • 自定义section会用到
    • __str__
    li = list([11, 22, 33, 44]) # ls是一个对象
    print(li[1]) # 对象名[index]
    li[1] = 'index' # 对象名[index] = value
    del li[1] # del 对象名[index]
    print(li) # 打印对象
    print(str(li)) # str(对象名)
    
    # li是list类的一个对象,通过类似的,我们自己创建的一个对象
    
    class Cat:
        def __getitem__(self, item):
            print('getitem', item)
        def __setitem__(self, key, value):
            print('setitem', key, value)
        def __delitem__(self, key):
            print('delitem', key)
    
    cat = Cat()
    cat[1] # getitem 1
    cat['k1'] # getitem k1
    cat['key'] = 'value' # setitem key value
    del cat['key'] # delitem key
    
    # 通过切片时:
    cat = Cat()
    cat[1:2:3] # getitem slice(1, 2, 3)
    cat[1:2:3] = 123 # setitem slice(1, 2, 3) 123
    del cat[1:2:3] # delitem slice(1, 2, 3)
    
    # python2.7中操作切片时会调用:
    # __getslice__
    # __setslice__
    # __delslice__
    # 在python3.x中会调用:
    # __getitem__
    # __setitem__
    # __delitem__
    
    #==========================
    # 直接打印对象会调用对象的__str__()
    # 将对象转字符串也会调用__str__()
    class Cat:
        def __str__(self):
            return '调用str方法'
    
    cat = Cat()
    print(cat)
    print(str(cat))
    
    • dict:查看成员(比较重要)
      • 应用:自定义form框架的时候用
      • 获取对象里面所有的字段
    class Cat:
        def __init__(self, name):
            self.name = name
        def show(self):
            pass
        def fun(self):
            pass
    
    ret = Cat.__dict__
    print(ret)# {'__module__': '__main__', 'fun': <function Cat.fun at 0x102173ae8>, 'show': <function Cat.show at 0x102173a60>, '__weakref__': <attribute '__weakref__' of 'Cat' objects>, '__dict__': <attribute '__dict__' of 'Cat' objects>, '__init__': <function Cat.__init__ at 0x1021739d8>, '__doc__': None}
    obj = Cat('yhh')
    ret = obj.__dict__
    print(ret) # {'name': 'yhh'}
    
    • iter:
      • for循环对象时会调用__iter__方法
    li = list([11, 22, 33, 44, 55])
    for item in li:
        print(item)
    # li是list类的对象,for循环li对象时会遍历得到结果
    # 自定义对象遍历:
    class Cat:
        def __iter__(self):
            yield 11
            yield 22
            yield 33
            yield 44
    
    cat = Cat()
    for item in cat:
        print(item)
    
    • __new__ & __metaclass__

      • python中一切皆对象,类是对象,模块是对象,类创建的也是对象
      • 解析器解析到class关键字就会创建类对象(默认由type创建)
      class Cat:
          __metaclass__ = xxx # 表示由xxx来创建这个类
      # 创建类:
      Cat = type(Cat, (object,),{"fun1":func}
      # type(类名,(基类,..),{成员})
      

异常

  • 编程难免遇到报错,如web网页尽量避免大黄页,应该让用户看到有好的错误页面.
try:
    # 需要保护的代码
    li = [11, 2, 3]
    ret = li[5]
except IndexError as IE:
    # 遇到异常时执行的代码块
    print(IE)
except Exception as e:
    # 遇到异常时执行的代码块
    print(type(e))
else:
    # 没有异常时执行的代码块
    print('no exception')
finally:
    # 不管有没有异常都会执行的代码块
    print('finally')
  • 异常分类:
    • 所有异常都是Exception的派生类
  • 主动触发异常
raise Exception('异常')

try:
    raise Exception('发生异常')
except Exception as e:
    pass
  • 断(意义不大)
assert 1 == 1
assert 2 == 1
# 如果为真,则真
# 如果为假,则抛异常
# 做测试用,限制软件的运行环境等
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容