• Python全栈开发之7、面向对象编程进阶-类属性和方法、异常处理和反射


    一、类的属性

    1、@property属性

    作用就是通过@property把一个方法变成一个静态属性

    class Room:
    
        def __init__(self,name,length,width,height):
            self.name=name
            self.length=length
            self.width=width
            self.height=height
    
        @property    
        def cal_area(self):
    
            return self.length*self.width
    
    r1=Room("room1",100,100,100)
    print(r1.cal_area)  
    class Flight(object):
        def __init__(self,name):
            self.name=name
    
    
        def checking_status(self):
    
            print("checking flight %s status"%self.name)
    
            return 1
    
        @property
        def flight_status(self):
    
            status=self.checking_status()
            if status==0:
                print("flight has canceled")
            elif status==1:
                print("flight has arrived")
            else:
                print("cannot confirm the flight status...,please check later")
    
        @flight_status.setter  # 修改属性
        def flight_status(self, status):
            status_dic = {
                0: "canceled",
                1: "arrived",
                2: "departured"
            }
    
    
            print("33[31;1mHas changed the flight status to 33[0m", status_dic.get(status))
    
    
    
    f=Flight("东方航空")
    
    
    f.flight_status
    f.flight_status=2
    示例

    二、类的方法

    1、类方法@classmethod

    供类使用的方法,类级别调用

    class Room:
        tag="一居室"
        def __init__(self,name,length,width,height):
            self.name=name
            self.length=length
            self.width=width
            self.height=height 
    
        @classmethod
        def roomInfo(cls):  #cls是自动生成的,类方法只能访问类变量,不能访问实例变量
            print(cls.tag)
    
    Room.roomInfo()  #通过类直接调用

    2、静态方法 @staticmethod

    通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法.

    普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

    class Dog(object):
    
        def __init__(self,name):
            self.name=name
    
        @staticmethod              # 静态方法跟类没什么关系  相当于普通函数
        def eat(name,food):        # 把eat方法变为静态方法
            print("%s is eating %s"%(name,food))
    
    Dog.eat('alex',"面包")
    class Dog(object):
    
        def __init__(self,name):
            self.name=name
    
        @staticmethod         #静态方法跟类没什么关系  相当于普通函数
        def eat(self):            #把eat方法变为静态方法
    
            print("%s is eating food"%self.name)
    
    
    d=Dog("xiaoming")
    d.eat()     #这样调用会报错 

     报错如下:说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

    Traceback (most recent call last):
      File "D:/python/day7/静态方法.py", line 23, in <module>
        d.eat()
    TypeError: eat() missing 1 required positional argument: 'self'

    想让上面的代码可以正常工作有两种办法

    1. 调用时主动传递实例本身给eat方法,即d.eat(d) 

    class Dog(object):
    
        def __init__(self,name):
            self.name=name
    
        @staticmethod       
        def eat(self):
    
            print("%s is eating food"%self.name)
    
    d=Dog("xiaoming")    
    d.eat(d)     #这样调用 或者Dog.eat(d)
    在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了

    三、isinstance(obj,cls)和issubclass(sub,super)

    class Foo:
        pass
    
    f1=Foo()
    
    #判断一个对象是否是一个类的实例
    print(isinstance(f1,Foo))
    # 返回 True
    isinstance(obj,cls)判断一个对象是否是一个类的实例
    class Foo:
        pass
    
    
    class Bar(Foo):
        pass
    
    # 判断一个类是否是另一个类的子类
    print(issubclass(Bar,Foo))
    # 返回 True
    issubclass(sub,super)判断一个类是否是另一个类的子类

    四、类的特殊成员方法

    1.__doc__ 方法 

    class Foo:
        """ 描述类信息 """
     
        def func(self):
            pass
     
    print (Foo.__doc__)
    #输出:描述类信息
    __doc__方法:类的文档描述信息 

    2.__module__ 和  __class__  

    __module__ 表示当前操作的对象在那个模块

    __class__     表示当前操作的对象的类是什么

    3. __init__ 构造方法,通过类创建对象时,自动触发执行

    4. __del__  : 析构方法,当对象在内存中被释放时,自动触发执行

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,

    所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

    5. __call__ 方法 : 对象后面加括号,触发执行

    class Dog(object):
    
        def __init__(self, name):
            self.name = name
    
        def __call__(self, *args, **kwargs):
            print(args, kwargs)
    
    
    d = Dog("Jim")
    
    d()  # 对象加括号() 就执行__call__方法
    __call__()方法

    6.  __dict__ 查看类或对象中的所有成员 

    7.  __str__  :如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值 

    class Dog(object):
       
    
        name='jim'
    
        def __init__(self,name):
            self.name=name
    
    
        def __str__(self):
    
           return "__str_"
    
    
    d=Dog("Jim")
    
    print(d)         #打印对象时  输出__str__方法的返回值而非内存地址
    __str__()方法 

     6. __new__和 __metaclass__方法

    class Foo(object):
    
        def __init__(self,name):
            self.name=name
    
        def __str__(self):
    
            return self.name
    
    
    
    f=Foo("xiaoming")
    
    print(f)
    print(type(f))
    print(type(Foo))   #Foo()类也是由type类实例化产生
    
    
    输出:
    xiaoming
    <class '__main__.Foo'>
    <class 'type'>

    上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

    如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

    所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

    五、反射

    主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    1、hasattr()方法

    hasattr(object, name)  判断object中有没有一个name字符串对应的方法或属性

    2、getattr()方法

    getattr(object, name, default=None)  去object对象中获取name成员内存地址

    3、setattr()方法

    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
    
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass
    #   setattr是给一个对象添加一个新的属性或方法

    4、delattr()方法

    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
    
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    def talk(self):
        print("%s is talking"%self.name)
    
    class Dog(object):
        def __init__(self,name):
            self.name=name
    
        def eat(self):
    
            print("%s is eating .."%self.name)
    
    
    
    d=Dog("哈巴狗")
    
    choice=input(">>:").strip()
    #
    # print(hasattr(d,choice))   #反射 hasattr 判断一个对象里是否有对应的字符串的属性方法映射
    #
    # print(getattr(d,choice))   #相当于print(d.eat)  得到eat的内存地址
    #
    # func=getattr(d,choice)     #根据字符串去获取obj对象里的对应的方法的内存地址,没有就会报错
    # func()
    
    setattr(d,'age',18)        # 给对象设置一个属性
    print(d.__dict__)          # 查看d的属性
    
    setattr(d,choice,talk)     #设置一个函数属性,相当于d.choice=talk  把talk的内存地址赋给了对象d.choice
    setattr(d,"func1",lambda x:x+1)
    
    func=getattr(d,choice)
    print(d.__dict__)
    func(d)
    
    delattr(d,choice)          # 删除属性
    示例

    5、__getattr__()方法和__getattrbute__()方法

    class FileHander:
    
        def __init__(self,filename,mode='r',encoding="utf-8"):
            print(mode)
            self.file=open(filename,mode=mode,encoding=encoding)
    
        def __getattr__(self, item):
    
            return getattr(self.file,item)
    
    
    f1=FileHander("a.txt",'a+')
    
    f1.write("222222")
    f1.seek(0)
    data=f1.read()
    
    print(data)
    __getattr__()没有属性就会调用该方法 
    class Foo:
        def __init__(self,age):
    
            self.age=age
    
        def __getattr__(self, item):
    
            print("执行的是getattr")
    
        def __getattribute__(self, item):
            print("执行的是getattrbute")
    
    f1=Foo(18)
    print(f1.name)  # 访问不存在的属性,如果没有__getattrbute__()方法,会触发__getattr__()方法
    print(f1.age)   # 否则有或者没有该属性都会触发__getattrbute__()方法
    __getattrbute__()方法

    6、__getitem__()和__setitem__()、__delitem__()方法

    class Foo:
    
        def __init__(self,age):
            self.age=age
    
        def __getitem__(self, item):
    
    
            print("get item")
            return self.__dict__[item]
        def __setitem__(self, key, value):
    
            self.__dict__[key]=value
            print("set item")
    
        def __delitem__(self, key):
            self.__dict__.pop(key)
            print("del item")
    
    
    f1=Foo(18)
    
    f1['name']="allen"
    
    print(f1.__dict__)
    
    print(f1['name'])
    print(f1.name)
    print(f1['age'])
    del f1['name']
    方法示例--中括号方式操作属性

     7、__format__()方法

    date_format_dict={'ymd':"{0.year}-{0.month}-{0.day}",
                      'm-d-y':"{0.month}-{0.year}-{0.day}",
                      'y:m:d':"{0.year}:{0.month}:{0.day}"}
    
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
    
        def __format__(self, format_spec):
    
            if not format_spec or format_spec not in date_format_dict:
                format_spec="ymd"
            fm=date_format_dict[format_spec]
            return fm.format(self)
    
    
    d=Date(2019,11,18)
    
    # x="{0.year}-{0.month}-{0.day}".format(d)
    # print(x)
    
    print(format(d))
    print(format(d,'y:m:d'))
    __format__(self, format_spec)方法

    六、异常处理

    在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是显示一个提示的页面,通俗来说就是不让用户看见大黄页!!!

    names=['jim','lucy']
    data={}
    print(type(data))
    s1='hello'
    
    try:                             #异常处理
        #open('t.txt')
        # data['name']
        int(s1)
        names[2]
    
    
    # except  IndexError as e :      
    #     print("no names[2]",e)
    #
    # except KeyError as k:
    #     print("key error",k)
    
    except ValueError as e:           #python3 用as   python2.6 用
        print(e)
    
    except Exception as e:            #抓住所有异常错误
        print("出错了",e)
    
    
    else:
        print("一切正常")
    
    finally:
        print("不管有没有错,都执行")

     注意:python3 用as python2.6 用 ,      except ValueError , e:

    1、异常种类

    python中的异常种类非常多,每个异常专门用于处理某一项异常!!!

    常用异常:

    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
    更多异常

     2、异常处理

     2.1 多分支

    s1 = 'hello'
    try:
        int(s1)
    except IndexError as e:
        print(e)
    except KeyError as e:
        print(e)
    except ValueError as e:
        print(e)

    2.2 万能异常Exception

    s1 = 'hello'
    try:
        int(s1)
    except Exception as e:
        print(e)
    
    #4 多分支异常与万能异常
    #4.1 如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么骚年,大胆的去做吧,只有一个Exception就足够了。
    #4.2 如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。

    2.3 在多分支后来一个Exception

    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:
        print(e)

    2.4 异常的其他机构   

    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:
    #    print(e)
    else:
        print('try内代码块没有异常则执行我')
    finally:
        print('无论异常与否,都会执行该模块,通常是进行清理工作')

    2.5 主动触发异常

    try:
        raise TypeError('类型错误')
    except Exception as e:
        print(e)

    2.6 自定义异常

    class TestExceptipon(Exception):
        def __init__(self,msg):
            self.msg=msg
    
        def __str__(self):
    
            return 'asdasd'
    
    
    
    try:
        raise TestExceptipon('我的异常')   #触发自己写的异常
    
    except  TestExceptipon as e:
        print(e)

     2.7 assert断言

    import importlib
    
    lib=importlib.import_module("lib.aa")
    lib.test()
    
    print(lib.name)
    assert type(lib.name) is str   #断言lib.name是一个字符串就往下执行
    print('ok')
    print("okkk")
  • 相关阅读:
    php Composer 报ssl证书错误
    centos svn服务器安装
    nginx配置 php 单入口
    centos nginx 安装
    Zend Studio的配置和使用
    不要让别人笑你不能成为程序员
    10个用于Web开发的最好 Python 框架
    分析和解析PHP代码的7大工具
    php模拟用户自动在qq空间发表文章的方法
    PHP中实现MySQL嵌套事务的两种解决方案
  • 原文地址:https://www.cnblogs.com/sunhao96/p/7771036.html
Copyright © 2020-2023  润新知