python面向对象之封装、继承、多态及异常

测试一个对象有多少个引用:

#测试一个对象有多少个引用,用sys.getrefcount()
#
如果没有引用则抛异常
import sys
str=
10
print(sys.getrefcount(str))

运行结果:17

若没有引用则报异常如下:

Traceback (most recent call last):

 File "E:/python-workspace/python/Class/class-5.29.py", line 218, in <module>

   print(sys.getrefcount(m))

NameError: name 'm' is not defined

面向对象的三大特征:封装、继承、多态

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

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

一个类可以有多个子类

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

给父类传参的四种方式:

父类.属性,或self.属性或父类.__init__(self,参数)或super(父类,self).__init__(参数)四种方法

调用父类方法时:super().父类方法()

总结:当子类继承父类时,子类的构造方法应该包含父类和子类共同的属性,在子类的初始化方法中,将父类的属性传递给父类,子类的属性赋值给子类

方法重写:子类和父类同名不同参,子类重写了父类的方法,当生成子类对象时,调用的是子类重写的方法

如果子类重写的方法想调用父类的方法时,在子类方法中:父类.方法(self)或super().父类方法()

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

构造的顺序:祖父类、父类,本类

类继承object

私有属性、私有方法:均不能在类外面被调用

两个下划线开头,声明该方法为私有方法,只能在类的内部调用,不能在类地外部调用。

class JustCounter:
   
__secretCount = 0   #私有变量
   
publicCount = 0   #公有变量
   

    def count(self):
       
self.__secretCount+=1
       
self.publicCount +=1
       
print(self.__secretCount)
counter = JustCounter()
counter.count()
print(counter.publicCount)
print(counter._secretCount)        

运行结果:Traceback (most recent call last):

1

  File"E:/python-workspace/python/Class_5_31/继承.py", line 77, in <module>

1

   print(counter._secretCount)         #报错,实例不能访问私有变量

AttributeError: 'JustCounter' object has no attribute'_secretCount'

Process finished with exit code 1

多继承:类同时继承多个父类,class C(A,B),当有AB均有相同方法,而子类又重写时,调用谁的方法,如果子类没有方法,则调用哪个父类的方法?A

class Person:
    
    def __init__(self,name=None,age=None,sex=None):
        print("------person")
        self.name=name
        self.age=age
        self.sex=sex
        
    def __str__(self):
        return "我的姓名:{0},我的年龄:{1},我的性别:{2}".format(self.name,self.age,self.sex)
    
class Music:
    
    def __init__(self,piano=None):
        print("-------music")
        self.piano=piano
        
class Student(Person,Music):
    
    def __init__(self,name=None,age=None,sex=None,score=None,piano=None):
        print("------student")
        #给父类传参四种方式————————方式一:
        # Person.name=name
        #方式二:
        # Person.__init__(self,name,age,sex,score)
        #方式三:
        #self.age=age
        #self.sex=sex
        #方式四:
        super(Student,self).__init__(name,age,sex)
        self.score=score
        self.piano=piano

    def __str__(self):
        return "我的姓名:{0},我的年龄:{1},我的性别:{2},我的成绩:{3},我喜欢:{4}".format(self.name,self.age,self.sex,self.score,self.piano)
stu=Student("Mary",23,"",88,"钢琴")
print(stu)

注意: 
1、super().__init__相对于类名.__init__,在单继承上用法基本无差  
2、但在多继承上,super保证每个父类只会被重写一次,如果使用类名调用时,就会出现多次调用  
3、多继承时,使用super方法,对父类的传参,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错  
4、多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法,只需写一句话便执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因。 

类属性和方法

类属性:属于类成员,属于对象共有

类方法:在方法上添加@classmethod

可以通过类方法调用类属性,也可以通过对象调用类属性

__new__(cls):#用来创建对象,而且必须有返回值

 return object.__new__(cls)

可以用id(cls)看地址

当有属性时,需要在__new__()中也添加属性

class A:
    @classmethod
    def __new__(cls,*args,**kwargs):
        print("-----new")
        return object.__new__(cls)
    @classmethod
    def test(abc):
        print("这是一个类方法"

静态方法:方法前加@staticmethod,静态方法没有参数,静态方法既和类没关系,也和对象没关系,也可以通过类和对象调用

@staticmethod
def staticmethod():
    print("这是一个静态方法")

单例模式:

要点:一是某个类只能有一个实例

        二是它必须自行创建这个实例

        三是它必须自行向整个系统提供这个实例

#实现__new__方法 
#并在将一个类的实例绑定到类变量_instance
#如果cls._instanceNone说明该类还没有实例化过,实例化该类,并返回 
#如果cls._instance不为None,直接返回cls._instance 

class SingLeTone:
    __instance=None
    def __new__(cls):
        if cls.__instance==None:
            cls.__instance=object.__new__(cls)
            return cls.__instance
        else:
            return cls.__instance
s=SingLeTone()
ss=SingLeTone()
print(id(s),id(ss))

运行结果:

91371440 91371440

对象列表排序:重写lt或gt方法

class Car:
    def __init__(self,brand=None,price=None):
        self.brand=brand
        self.price=price

    def __gt__(self,other):
        #支持中文排序:用encode()进行编码
        return self.brand.encode("gbk")<other.brand.encode("gbk")
        #return self.price<other.price
    def __str__(self):
        return self.brand+str(self.price)
lists=[Car("英菲尼迪",300000),Car("奥迪",350000),Car("奔驰",400000)]
lists.sort()
for i in lists:
    print(i)

多态

多态(从定义角度触发):同一类事物的多种形态。一个抽象类有多个子类,因而多态的概念依赖于继承

多态性(从使用角度触发):同一种调用方式,不同的执行效果。

class Animal:
   
def run(self):
       
raise AttributeError('子类必须实现这个方法')

class People(Animal):
   
def run(self):
       
print('人正在走')

class Pig(Animal):
   
def run(self):
       
print('pig is walking')

class Dog(Animal):
   
def run(self):
       
print('dog is running')

peo1=People()
pig1=Pig()
d1=Dog()
#实例化调用方法得到的结果
#peo1.run()
#pig1.run()
#d1.run()

#
多态性:一种调用方式,不同的执行效果(多态性)
# 多态性依赖于:继承

##多态性:定义统一的接口,
def func(obj): #obj这个参数没有类型限制,可以传入不同类型的值
   
obj.run() #调用的逻辑都一样,执行的结果却不一样

func(peo1)
func(pig1)
func(d1)

多态性的实质:实质就是定义了一个函数接口,在这个函数中定义了所有类通用的函数功能,只要传入参数(即对象名),函数调用执行就能得到不同的结果。上述即一种调用方式,不同的执行结果。

异常:运行期检测到的错误

异常是python对象,表示一个错误

当脚本发生异常时需要捕获并处理,否则程序会终止执行

异常产生的时机,系统产生

异常处理

捕获异常:try/except语句

try..except..else

使用except可不带任何异常类型,也可带多种异常类型

try-finally 语句无论是否发生异常都将执行最后的代码。

eg:

def device():
   
try:
       
1/0
   
except ZeroDivisionError:
       
print("除数不能为0")
device()

运行结果:除数不能为0

也可用as定义别名,即输出自己的信息。

def device():
    try:
        1/0
    except ZeroDivisionError as zd:
        print("除数不能为0")
        print(zd)
device()

运行结果:division by zero

触发异常

使用raise语句

语法格式:

raise [Exception [, args [, traceback]]]

语句中Exception是异常类型(例如,NameError)参数标准异常中任一种,args是自已提供的异常参数

最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。

用户自定义异常:

创建一个新的异常类,程序可命名自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。

eg:实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。

#自定义异常
class Networkrror(RuntimeError):
   
def __init__(self,args):
   
     self.args=args
#触发异常
try:
   
raise Networkrror("Badhostname")
except Networkrror:
   
print(Networkrror.args)

 

猜你喜欢

转载自blog.csdn.net/candriy/article/details/80527219