python中继承和异常

python可以查询一个类有多少个引用,不过使用该方法,需要一个模块

#查看引用
import sys
class Student(object):
    pass
student = Student();
print(sys.getrefcount(student))
如果删除刚刚创建好的引用,就会报错
del student
print(sys.getrefcount(student))

   错误信息 : NameError: name 'student' is not defined

继承:

   当我们定义一个类的时候,可以从某个类继承,继承的类,就被称之为派生类或者叫做子类,

    而被继承的类称为基类、父类或者超类

子类继承父类,子类可以使用父类的属性和方法,简化代码.

当生成子类对象时,先初始化父类对象,所以如果父类有__init__()方法,并且有属性时,要通过子类的构造赋值。

class Person(object):
    #父类
    def __init__(self,name,age):
         self.name = name
         self.age = age
    def run(self):
        print("父类中的方法run")
class Student(Person):
    #子类,继承person
    def __init__(self,name,age,sex):
        self.name  = name
        self.age = age
        self.sex=sex
    def __str__(self):
        return "我的名字是:{0}年龄为:{1}我的性别是:{2}".format(self.name,self.age,self.sex)
student = Student("张三",19,"男")
print(student)
#子类没有run方法,但子类可以使用父类的run方法
student.run()

打印结果:

     我的名字是:张三年龄为:19我的性别是:男

    父类中的方法run

多继承:

     python同样支持多继承,一个子类可以有多个父类。

 子类传递参数给父类: 

           在子类中,调用父类的属性时,在__init__()方法中使用

      父类.属性,或self.属性或父类.__init__(self,参数)或super(父类,self).__init__(参数)四种方法给父类传参
     调用父类方法时:super().父类方法()

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法

三代继承:子类初始化方法需要祖父、父类及自己的属性,可以调用父类的初始化方法传参,可以重写父类的方法

构造的顺序依然先构造祖父类,再构造父类,最后构造自己 

方法重写:
如果子类重写的方法想调用父类的方法时,在子类方法中:父类.方法(self)或super().父类方法()
私有属性、私有方法:均不能在类外面被调用
多继承:类同时继承多个父类,class C(A,B),当有AB均有相同方法,而子类又重写时,调用子类的方法,如果子类没有方法,则调用从左到右第一个父类的方法。

类名.mro(),可以看到所有父类,即搜索顺序。

多态:

    多态是指一类事务有多种形态,一个类有多个子类,从而形成了多态

    

class Person(object):
    #定义一个方法什么也不做,子类负责实现该方法
    def run(self):
        pass
class Student(Person):
    #重写父类方法
    def run(self):
        print("学生再跑")
class Teacher(Person):
     #重写父类的方法
     def run(self):
         print("老师在跑")
person = Student()
person.run()
person = Teacher()
person.run()
运行结果:

       学生再跑

       老师在跑

结论:  通过不同的子类,得到的内容也不相同!

类属性:属于类的成员,属于对象共有的,不在方法体内定义
类方法:在方法上添加@classmethod
@classmethod
def class_method(cls):
可以通过类方法调用类属性,也可以通过对象调用类属性
静态方法:方法前加@staticmethod,静态方法没有参数,静态方法既和类没关系,也和对象没关系,也可以通过类和对象调用
工厂类:有一些子类,在一个类中生成很多对象,简单工厂模式

class Cat(object):
    # 类属性
    num = 0
    row=100
    @classmethod
    def leiMethod(self,name):
        print("这是类方法",name)
    @staticmethod
    def smethod():
        #静态方法是没有参数的
        print("这是静态方法")
    def __init__(self):
            #实例属性
            self.age = 1
            #如类属性的名字和实例属性的名字相同,那么通过,对象获取num的时候
            #那么会获取实例属性的值
            self.num = 100
    def run(self):
         print("-----猫在跑---")
mao = Cat()
#使用对象去访问
print(mao.num)  #100
#常用的方式 使用类去访问类属性
print(Cat.num)  #0
Cat.num+=1
print(Cat.num) # 1
print(mao.row) # 100
#是用对象修改类属性,相当于创建了一个实例属性,并没有修改类属性
mao.row+=400
print(mao.row) #500
print(Cat.row) #100
#调用类方法
Cat.leiMethod("张三")
#调用静态方法
Cat.smethod()
函数:
__init(self)__  : 对象创建完之后会调用默认调用该函数,主要用于完成对象的初始化设置
__new__(cls)的使用:
      def __new__(cls, *args, **kwargs):
        print("---------new-------")
        return object.__new__(cls)
     对象创建的过程中会调用该函数,比__init__()函数,要先执行,不过该函数
     一定要有返回值,cls指的是,当前这个类
当有属性时,需要在__new__()中也添加属性
 
 
class Test(object):
    def __init__(self,name):
        self.name = name
    #如果__init__有参数的话,那么__new__()函数要这么写,不然会报异常
    def __new__(cls, *args, **kwargs):
        print("这是 new")
        return object.__new__(cls)
    def  __str__(self):
        return "名字为:{0}".format(self.name)
test = Test("张三")
print(test)
单例模式

一个类不论实例化多少次,用函数id(变量),得到的地址值是不变的,是一样的
#单例
class Singleton(object):
    __instance = None
    def  __new__(cls, *args, **kwargs):
       if cls.__instance == None:
           cls.__instance = object.__new__(cls);
       return cls.__instance
a = Singleton()
print(id(a))
b = Singleton()
print(id(a))
对象列表进行排序:按照什么进行排序,重写__lt__方法:


class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):
        return "姓名:%s,年龄:%d"%(self.name,self.age)
    def __lt__(self, other):
        if self.name==other.name:
            return self.age<other.age
        else:
            return self.name.encode('gbk')>other.name.encode('gbk')
支持中文排序


peple=[Person("abc",20),Person("aabc",22),Person("abc",21),Person("aabc",23)]
peple.sort()
for m in peple:
    print(m)

还可以使用切片,进行排序

lists2 = [Car("宝马2", 2002), Car("奥迪2", 1002), Car("野马2", 3002), Car("大奔2", 6002)]
lists2.sort(key=lambda x:x.price,reverse=True)
for i in lists2:
    print(i,end=" ")
异常:
    即有一些代码语法正确,但运行时会发生错误,运行期检测的错误被称为异常。
    解决异常:
     1.捕获多个异常 try:...except:..
        try:
           print(1/0)
        except 异常的名字: #还可以显示异常的基本信息  except 异常的类型 as 随便一个名字:
                           # print(随便一个名字)就可以输出异常的基本信息
           print("提示出现的异常,并给出对应解决方法")
        except 异常的名字:
           print("提示出现的异常,并给出对应解决方法")
         ......可以有多个

     2.#捕获全部异常
        try:
            print(1/0)
        except : #加个冒号,如果想捕获异常信息就需要这样写  except Exception as ex:
            print("出现异常")
     3.else,代表没有异常的时候会执行else
            try:
                #如果产生了一个异常,但是except没有捕获,那么就会按照这个异常默认的处理方式进行处理
                a=100
                print(a)
            except Exception as ex:
                print("出现异常",ex)
            else:
                #在try中代码都没有产生异常的时候,才会执行的代码
                print("-----else--------")
     4.try:...finally:...
          在程序中,如果一个代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。
            try:
                print(a)
            except Exception as ex:
                print("出现异常",ex)
            else:
                print("-----else--------")
            finally:
                #最后执行
                print("这是finally")
     5.自定义异常
            #自定义异常
            class Test(Exception):
                def __init__(self,length,atleast):
                    self.length = length
                    self.atleast=atleast
                 try:
                #手动抛出异常,确保抛出异常的类要继承Exception
                #手动抛出异常的关键字
                raise Test(1,2)
            except Test as ex:
                print("testtetste")
            print(ex)

猜你喜欢

转载自blog.csdn.net/weixin_42238444/article/details/80553708