zoukankan      html  css  js  c++  java
  • 面向对象之 类的成员与异常处理

    面向对象之 类的成员与异常处理

    细分类的组成成员

    class A:
    
        company_name = '老男孩教育'  # 静态变量(静态字段)
        __iphone = '1353333xxxx'  # 私有静态变量(私有静态字段)
    
    
        def __init__(self,name,age): #特殊方法
    
            self.name = name  #对象属性(普通字段)
            self.__age = age  # 私有对象属性(私有普通字段)
    
        def func1(self):  # 普通方法
            pass
    
        def __func(self): #私有方法
            print(666)
    
    
        @classmethod  # 类方法
        def class_func(cls):
            """ 定义类方法,至少有一个cls参数 """
            print('类方法')
    
        @staticmethod  #静态方法
        def static_func():
            """ 定义静态方法 ,无默认参数"""
            print('静态方法')
    
        @property  # 属性
        def prop(self):
            pass
    

    类的私有成员 公有 / 私有 成员

    • 公有成员,在任何地方都能访问 (继承)
    • 私有成员,只有在类的内部才能访问

    (公有) 静态字段 / 静态属性

    • 公有成员( 静态字段 / 方法),在任何地方都能访问 / 类访问 / 类内部可以访问 / 派生类中可以访问
    # 公有静态字段 -----------------------------
    class C:
        name = "公有静态字段"
        def func(self):
            print(C.name)
    
    class D(C):
        def show(self):
            print(C.name)
            print(self.name)
    
    print(C.name)         # 类访问
    obj = C()
    obj.func()     # 类内部可以访问
    
    obj_son = D()
    obj_son.show() # 派生类中可以访问
    

    私有成员 *

    • python中所有的私有成员 : 就是在私有成员前面加上 _类名 的加密方式而已
    • print(类名 . _类名__私有成员) 即可访问到 (少用)
    • 私有成员,只能在 本类 内部进行访问, 类的 外部 / 派生类 / 子类 均不可访问
    • 私有静态字段 / 普通字段 / 方法:仅类内部可以访问;或者通过本类内部的共有方法访问 (间接访问)
    • 调用私有成员时, 尽量都用self. + 私有成员 使用方便 / 万能self

    用途

    • 设定一些私有的或者是不想让类外面用到,密码,加密方式,等设置成私有成员
    # 私有静态字段 -----------------------------  
    # 调用私有成员时, 尽量都用self. + 私有成员 使用方便 / 万能self
    class C:
         __name = "私有静态字段"
        def __init__(self,age):
            self.__age = age  # 私有对象属性 
        def __f(self):  # 私有方法 
            print(666)
       
        def func(self): # 共有方法
            print(self.__age)  #  私有对象属性必须用self传参
            print(self.__name) # 私有静态字段 类名. self. 都可以
            print(C.__name) # 私有静态字段 类名.  都可以
            A.__func("1")  # 私有方法 用类名 .  使用必须传参
            self.__f() # 私有方法 用self. 不用传参 self自动传参
    
    class D(C):
    
        def show(self):
            print(C.__name)
    
    
    # C.__name       # 不可在外部访问 
    obj = C()
    # obj.__name  # 不可在外部访问
    obj.func()     # 通过 类内部的共有方法 可以访问
    
    obj_son = D()
    obj_son.show() #不可在派生类中可以访问
    

    类的其他成员

    • 方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同

    类方法 @classmethod **

    • 定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)
    • 使用装饰器@classmethod
    • 类名 . + 类方法()
    # 类方法练习
    class Student:
        __num = 0
        def __init__(self,name,age):
            self.name = name
            self.age= age
            Student.addNum()  # 写在__new__方法中比较合适,但是现在还没有学,暂且放到这里
    
        @classmethod
        def addNum(cls): # cls 相当于普通类中的self cls传递类名   self一般传递实例对象
            cls.__num += 1
    
        @classmethod
        def getNum(cls):  # cls传递类名
            return cls.__num
    
    a = Student('太白金星', 18)
    b = Student('武sir', 36)
    c = Student('alex', 73)
    print(Student.getNum()) # 3   
    

    静态方法 @staticmethod **

    不依赖于类, 也不依赖对象, 就是一个普通的函数

    • 定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;
    • 调用:实例对象 和 类对象 都可以调用

    静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护

    import time
    
    class TimeTest(object):
        def __init__(self, hour, minute, second):
            self.hour = hour
            self.minute = minute
            self.second = second
    
        @staticmethod
        def showTime():  # 是个独立的函数 只是存放在类中  维持一种逻辑关系 
            return time.strftime("%H:%M:%S", time.localtime())
    
    
    print(TimeTest.showTime())
    t = TimeTest(2, 10, 10)
    nowTime = t.showTime()
    print(nowTime)
    

    使用了静态方法(函数),然而方法体中并没使用(也不能使用)类或实例的属性(或方法)。若要获得当前时间的字符串时,并不一定需要实例化对象,此时对于静态方法而言,所在类更像是一种名称空间。

    其实,我们也可以在类外面写一个同样的函数来做这些事,但是这样做就打乱了逻辑关系,也会导致以后代码维护困难。

    属性 @property 常用/ @setter (修改) / @deleter(删除) **

    • 将方法伪装成属性 , 进行 查 修 删
    • 代码级别没有提升
    • 设置属性时, 你的对象一定不能出现同名的属性
    • @property 常用
    • @setter (修改) 这个装饰器装饰的函数不能使用return
    • @deleter(删除) 这个装饰器装饰的函数不能使用return
    class Bmi:
        def __init__(self, name, weight, height):
            self.name, self.weight, self.height = name, weight, height
    
        def bmi_(self):
            return self.weight / self.height ** 2
    
    
    ly = Bmi("李业", 70, 1.7)
    print(ly.bmi_()) # 此时bmi是方法  24.221453287197235
    
    
    class Bmi:
        def __init__(self, name, weight, height):
            self.name, self.weight, self.height = name, weight, height
        @property  # 只有在属性bmi_定义property后才能定义bmi_.setter,bmi_.deleter
        def bmi_(self):
            return self.weight / self.height ** 2
        @bmi_.setter # 下面的函数不能加ruturn
        def bmi_(self,v):
            print(v)
            print("修改的时候执行")
    
        @bmi_.deleter  # 下面的函数不能加ruturn
        def bmi_(self):
            print("删除的时候执行")
            
    
    
    ly = Bmi("李业", 70, 1.7)
    print(ly.bmi_)  # 此时bmi 已经伪装成属性了   24.221453287197235
    # 我们要让bmi方法伪装成属性,虽然在代码级别没有提成,但看起来更合理
    
    # property的简化使用
    class A:
        def get_aaa(self):
            print("get aaa")
    
        def set_aaa(self,v):
            print(v)
            print("set aaa")
    
        def del_aaa(self):
            print("del aaa")
        aaa = property(get_aaa,set_aaa,del_aaa) #内置property三个参数与get,set,delete一一对应
        # aaa 是属性名
    a = A()
    a.aaa
    a.aaa = 111
    del a.aaa
    

    商品价格修改示例

    class Goods(object):
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount  # 实际价格
            return new_price
    
        @price.setter
        def price(self, value): 
            self.original_price = value   # 修改属性 / 原价
    
        @price.deleter
        def price(self):
            del self.original_price  # 删除属性
    
    obj = Goods()
    print(obj.price)        # 获取商品价格
    obj.price = 200         # 修改商品原价
    print(obj.price)
    # del obj.price         # 删除商品原价
    print(obj.price)
    

    isinstance / 是否是实例

    • isinstance(a,b):判断 a对象 是否 是 b类(或者b类的派生类)实例化的对象
    class A:
        pass
    
    class B(A):
        pass
    
    obj = B()
    
    
    print(isinstance(obj,B)) # True
    print(isinstance(obj,A)) # True
    

    issubclass 是否子类

    issubclass(a,b): 判断 a类 是否 是 b类(或者b的派生类)的派生类

    class A:
        pass
    
    class B(A):
        pass
    
    class C(B):
        pass
    
    print(issubclass(B,A))  # True
    print(issubclass(C,A)) # True
    print(issubclass(C,B)) # True  继承顺序是C→B→A
    
    

    type 与 object

    type元类

    python中一切皆对象 , 一个类也是一个对象

    那这个(类)对象肯定是由类实例化出来的

    python中你创建的所有类,以大部分list str 等等这些类, 都是从type元类实例化得来的

    python中继承object类都是新式类

    object 也是由type元类实例化得来的

    判断一个类是不是可迭代对象还有一种方法

    s = [1,2,3,4]
    # 第一种
    print("__iter__" in dir(s)) # 判断是否是有 "__iter__"的方法
    # 第二种
    from collections import Iterable
    
    s = [1,2,3] 
    print(isinstance(s,Iterable)) # 两个结果都是True
    
    

    异常处理 ***

    错误分类

    • 异常处理 不能 经常使用: 异常处理 耗费性能.有些错误是需要进行分流使用.代码的可读性 变差.
    • 关键节点使用.

    语法错误

    • 这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正

    逻辑错误

    #用户输入不完整(比如输入为空)或者输入非法(输入不是数字)
    num=input(">>: ")
    int(num)
    
    #无法完成计算
    res1=1/0
    res2=1+'str'
    
    

    异常

    • 程序运行时发生错误的信号 , 异常之后的代码就不执行了
    • 程序出现中断,飘红,致使你的整个项目中断

    异常分类

    异常示例

    # 触发IndexError
    l=['egon','aa']
    l[3]
    # 触发KeyError
    dic={'name':'egon'}
    dic['age']
    
    #触发ValueError
    s='hello'
    int(s)
    
    

    常用异常

    AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
    IOError 输入/输出异常;基本上是无法打开文件
    ImportError 无法引入模块或包;基本上是路径问题或名称错误
    IndentationError 缩进错误 语法错误(的子类) ;代码没有正确对齐
    IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
    KeyError 试图访问字典里不存在的键
    KeyboardInterrupt Ctrl+C被按下
    NameError 使用一个还未被赋予对象的变量
    SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
    TypeError 传入对象类型与要求的不符合
    UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
    导致你以为正在访问它
    ValueError 传入一个调用者不期望的值,即使值的类型是正确的
    
    

    更多异常种类

    ArithmeticError
    AssertionError
    AttributeError
    BaseException
    BufferError
    BytesWarning
    DeprecationWarning
    EnvironmentError
    EOFError
    Exception
    FloatingPointError
    FutureWarning
    GeneratorExit
    ImportError
    ImportWarning
    IndentationError
    IndexError
    IOError
    KeyboardInterrupt
    KeyError
    LookupError
    MemoryError
    NameError
    NotImplementedError
    OSError
    OverflowError
    PendingDeprecationWarning
    ReferenceError
    RuntimeError
    RuntimeWarning
    StandardError
    StopIteration
    SyntaxError
    SyntaxWarning
    SystemError
    SystemExit
    TabError
    TypeError
    UnboundLocalError
    UnicodeDecodeError
    UnicodeEncodeError
    UnicodeError
    UnicodeTranslateError
    UnicodeWarning
    UserWarning
    ValueError
    Warning
    ZeroDivisionError
    
    

    异常处理

    python解释器检测到错误,触发异常(也允许程序员自己触发异常)
    程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)
    如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理

    异常处理的原因

    • 必须提供一种异常处理机制来增强你程序的 健壮性容错性
    • python解析器去执行程序,检测到了一个错误时,触发异常,异常触发后且没被处理的情况下,程序就在当前异常处终止,后面的代码不会运行,谁会去用一个运行着突然就崩溃的软件

    用 if 判断来进行异常处理

    • if是可以解决异常的,只是存在1,2的问题,所以,千万不要妄下定论if不能用来异常处理
    num1=input('>>: ') #输入一个字符串试试
    if num1.isdigit():
        int(num1) #我们的正常程序放到了这里,其余的都属于异常处理范畴
    elif num1.isspace():
        print('输入的是空格,就执行我这里的逻辑')
    elif len(num1) == 0:
        print('输入的是空,就执行我这里的逻辑')
    else:
        print('其他情情况,执行我这里的逻辑')
    
    '''
    问题一:
    使用if的方式我们只为第一段代码加上了异常处理,但这些if,跟你的代码逻辑并无关系,这样你的代码会因为可读性差而不容易被看懂
    
    问题二:
    这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。
    '''
    
    

    python异常处理的 '私人定制'

    基本语法

    try:
        被检测的代码块
    eceptx 异常类型:
        try中一旦检测到异常,就执行这个位置的逻辑
    
    

    异常类只能用来处理指定的异常情况

    # 未捕获到异常,程序直接报错
    try:
        s1 = 'hello'
        int(s1)  # 换成s1[111] 就会处理指定错误
    except IndexError as e:  # 这个是捕捉索引类型错误的 上面的错误是typeerror类型 没有捕捉到指定错误
        print(e)
        
    # 最后救过是系统自己报错
    
    

    单 / 多分支

    • 想要的处理方式是 : 对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支
    • 根据不同的异常执行不同的逻辑流程 → 采取多分支
    • 及时解决异常, 避免程序中断. 程序的分流.
    s = "sfsf"
    try:
        int(s)
    except IndexError as e:
        print(e)
    except KeyError as e:
        print(e)
    except ValueError as e:
        print(e)
    
    

    万能异常 Exception

    • 可以捕获任意异常

    使用场景

    • 无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理,一个Exception就足够了
    • 只是想把这个异常处理掉,让程序继续执行. 万能异常
    s1 = 'hello'
    try:
        int(s1)
    except Exception as e:
        print(e)
    
    
    s1 = 'hello'
    try:
        int(s1)
    except Exception as e:
        '丢弃或者执行其他逻辑'
        print(e)
    
    #如果你统一用Exception,没错,是可以捕捉所有异常,但意味着你在处理所有异常时都使用同一个逻辑去处理(这里说的逻辑即当前expect下面跟的代码块)
    
    

    多分支 + try + Exception + else + finally***

    s1 = 'hello'
    try:
        int(s1)
    except IndexError as e:
        print(e)
    except KeyError as e:
        print(e)
    except ValueError as e:
        print(e)
    #except Exception as e:  # Exception一定要放在多分支异常处理的下面 , 放在上面都会被其所捕捉, 不会执行下面的异常处理
    #    print(e)
    else:  # 如果上面无异常执行else语句,否则不执行else语句.
        print('try内代码块没有异常则执行我')
    finally:  # 在代码发生错误之前执行其下面的代码  / 异常或奔溃瞬间保存
        print('无论异常与否,都会执行该模块,通常是进行清理工作') 
    
    

    finally

    • 这个异常自己判断程序何时终止或者中断,在终止或者中断前,执行finally下面的代码
    • 数据库: 连接数据库引擎

    主动触发异常

    • raise Exception(需要提示的异常语句)
    try:
        raise TypeError ("错误类型")
    except Exception as e:
        print(e)
    
    

    断言

    • assert 条件 下面写源码
    assert 1 == 1 # 写在源码上面去判断
    print(111)
    print(222)  # 111 222
    
    
    assert 1 == 2
    print(111)
    print(222)  # AssertionError
    
    

    自定义异常

    class Connection(BaseException):
        def __init__(self,msg):
            self.msg = msg
    raise Connection("触发连接异常")
    
    
  • 相关阅读:
    osg模型部分节点旋转
    IFC数据模型构件控制
    自定义基于IFC数据的施工进度数据结构
    QDateTime QString
    Qt获取屏幕分辨率
    Qt自定义类重写 copy
    removeEntry
    initGanttView
    IfcAxis2Placement3D IFC构件的位置和方向
    致我最爱的你
  • 原文地址:https://www.cnblogs.com/fanxss/p/11219200.html
Copyright © 2011-2022 走看看