Python编程:09- 面向对象--反射(单例模式)&继承&重写&多态

1、面向对象基础版本

用以下例子做说明:
1、新建一个长方形的类,这个类的属性,方法包含所有长方形的公共的属性和方法

class Rectangle:  
     list1=[10,20,30,40,50]   # 类属性,具有唯一性
     def __init__(self,length,width):  # 初始化方法  长方形都有长宽
         self.length=length  # 将用户传的length转为实例自身的length
         self.width=width  # 将用户传的width转为实例自身的width
         self.list2 = [10, 20, 30, 40, 50,60]  # 实例属性,不唯一
     
     def permiter(self):  # 周长方法,所有长方形都是一个算法,公共的算法
         return (self.length+self.width)*2

     def area(self):  # 面积方法,所有长方形都是一个算法,公共的算法
         return self.length*self.width
 
 rec=Rectangle(5,4)  # 实例化,定义一个具体的长方形
 print(rec.permiter())  # 计算具体的长方形的周长
 print(rec.area())     # 计算具体的长方形的面积
 print(rec.__dict__)  # 查看实例的属性
 print(rec.list2)  
 
 rec1=Rectangle(10,8)
 rec2=Rectangle(8,6)
 print(id(rec1.list1)==id(rec2.list1))  # 结果为Ture, 所有的实例, 共用一个类属性
 print(id(rec1.list2)==id(rec2.list2))  # 结果为Flase, 每个实例,使用各自的实例属性

反射:实现去对象中操作成员(以字符串的形式去对象中进行成员的操作)

  • hasattr :对象中是否包含成员,hasattr (对象,'成员名称',值)
  • getattr:去对象中获取成员,getattr(对象,'成员名称',值)
  • setattr:去对象中设置成员,setattr(对象,'成员名称',值)
  • delattr:删除对象中的成员,delattr(对象,'成员名称',值)
print(hasattr(str,'replace'))   # 在对象里找有没有某个属性或方法, 返回值是布尔型
 print(hasattr(Rectangle,'list2'))  # 类没有list2, 返回Flase
 print(hasattr(rec,'list2'))   # 实例有list2,返回Ture
 print(getattr(str,'replace'))  #在对象里找有没有某个属性或方法,返回值是属性或方法本身
 print(getattr(str,'replace123','没有找到对应的属性或方法'))  #找不到属性或方法返回指定的值
 
 # setattr  在对象里新增或修改属性值
 class Class1:
     a=1
     def __init__(self):
         pass
 setattr(Class1,'a',100)  #将属性a设置为100
 setattr(Class1,'b',200)  #新增属性b,并设置为200
 print(Class1.a)
 print(Class1.b)

反射的应用:

  • 单例模式应用到了反射的原理,如下:
class Single:
     def __init__(self):  # 初始化方法
         pass
     def __new__(cls, *args, **kwargs):  # 构造方法,用于生成实例
         if not hasattr(cls,'obj'):  # 判断类当中有没有实例方法, 如果没有则新建
             cls.obj=object.__new__(cls)  # 生成实例对象
         return cls.obj  # 返回实例
  • 点菜系统列举
class Restaurant:
     def yuxiangrousi(self):
         return '鱼香肉丝'
     def gongbaojiding(self):
         return '宫爆鸡丁'
     def qingjiaotudousi(self):
         return '青椒土豆丝'
     def shousibaocai(self):
         return '手撕包菜'
     def kaishuibaicai(self):
         return '开水白菜'

while True:
     menu=input('请点菜:  ')
     if hasattr(Restaurant,menu):   
          # hasattr(对象,属性或方法名),判断对象中是否有某个属性或某个方法,返回值是布尔型
         print('好的,请厨师开始做菜')
         break
     else:
         print('没有这道菜')

2、面向对象进阶版本

class Rectangle:
     def __init__(self,length,width):  #初始化方法
         self.length=length  #将用户传的length转为实例自身的length
         self.width=width  #将用户传的width转为实例自身的width
     def perimeter(self):  #实例方法
         return (self.length+self.width)*2
     def area(self):  #实例方法
         return self.length*self.width
     @classmethod  #装饰器,声明下面的方法是类方法
     def features(cls):
         print('两边的长相等,两边的宽也相等,长和宽的角度为90度')
 
     @staticmethod  #装饰器,声明下面的方法是静态方法
     def sumdata(a, b):  #静态方法
         return a + b

方法的调用

调用实例方法:实例方法可以由实例调用,不可以由类调用
调用类方法: 类方法可以由类调用,也可以由实例调用
调用静态方法:静态方法既可以由类调用,也可以由实例调用

rec=Rectangle(5,4)  #实例化
 print(rec.perimeter())  #实例方法可以由实例调用,不可以由类调用
 print(rec.area())
 Rectangle.features()  #类方法可以由类调用,也可以由实例调用
 print(rec.sumdata(3,6))
 print(Rectangle.sumdata(3,6))  #静态方法既可以由类调用,也可以由实例调用

判断一个对象是方法还是函数,可以用type

print(type(rec.perimeter))  #返回值是method
 print(type(Rectangle.features))  #返回值是method
 print(type(Rectangle.sumdata))  #返回值是function
  • inspect模块
    某个对象是否是方法: inspect.ismethod()
    某个对象是否是函数: inspect.isfunction()
import inspect
 print(inspect.ismethod(rec.perimeter))  #True
 print(inspect.ismethod(rec.features))   #True
 print(inspect.ismethod(rec.sumdata))    #False
 print(inspect.isfunction(rec.perimeter))
 print(inspect.isfunction(rec.features))
 print(inspect.isfunction(rec.sumdata))
  • 继承
    (1) 完全继承,
class Square(Rectangle):
     pass
 squ=Square(6,6)
 print(squ.perimeter())
 print(squ.area())

(2)部分继承,重写父类的一些方法

class Square(Rectangle):
     def __init__(self,side):
         self.length=side
         self.width=side
 squ=Square(6)
 print(squ.perimeter())
 print(squ.area())

(3)全部重写,相当于没有继承

class Square(Rectangle):
     def __init__(self,side):
             self.side=side
     def perimeter(self):
         return self.side*4
     def area(self):
         return self.side**2
 squ=Square(6)
 print(squ.perimeter())
 print(squ.area())

(4)继承父类方法的同时,对父类的方法进行扩展

class Square(Rectangle):
     def __init__(self,side):
         self.length=side
         self.width=side
     @classmethod
     def features(cls):
         super().features()  #声明继承父类的方法
         print('长和宽也相等')
 Square.features()

@property 声明下面的方法是一个属性而不是方法

class Test1:
     a=[1,2,3]  #类的静态属性,具有唯一性
     def __init__(self):
         self.b=[4,5,6]  #实例的静态属性,不具有唯一性
     @property  #声明下面的方法作为一个属性而不是方法
     def fun1(self):
         return 'Hello'
 tt1=Test1()
 print(tt1.fun1)  #加了@property装饰器之后,作为属性进行调用

高级面向对象

  • 私有属性和私有方法: 私有属性:在属性的前面加上双下划线,就变成了私有属性.在方法的前面加上双下划线,就变成了私有方法,私有属性和私有方法不能被子类继承,也不能被直接调用.
#  __只在前面加,如果前后都有__,不是私有方法或私有属性
 class Class_test1:
     __str1='ABCDE'  #私有属性
     str2='QQQ'  # 非私有属性
     def __init__(self):
         pass
     def __method1(self):
         print('这是一个私有方法')
     def method2(self):
         print(self.__str1)  #在对外开放的方法里调用私有属性
         self.__method1()  #在对外开放的方法里调用私有方法
 cls1=Class_test1()
 print(cls1.__str1)  #私有属性不能被直接调用
 cls1.__method1()  #私有方法不能被直接调用
 print(cls1.str2)  #非私有属性可以直接调用
 cls1.method2()
  • 所有的类都是object的子类,一个类无论是否声明继承object,实际都继承
class Class10:
     '''
     天子呼来不上船
     自称臣是酒中仙
     '''

Class10继承了object,所以可以直接使用object里提供的方法

print(Class10.__dict__)  #显示类的属性
 print(Class10.__doc__)  #显示类的注释
 print(Class10.__base__)  #显示父类的名称
 print(Class10.__bases__)  #显示所有父类的名称
 print(Class10.__name__)  #显示类的名称
  • 多继承
class Money1:
     def money(self):
         print('一个亿')
 class Money2:
     def money(self):
         print('两个亿')
 class Man(Money1,Money2):  
     #继承多个父类时,用逗号隔开,多个父类中有同名方法时,按照继承顺序进行继承
     pass
 man=Man()
 man.money()
  • 多态,指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等。(一个抽象类有多个子类,因而多态的概念依赖于继承)
  • 多态性是 : 一个接口,多种实现
    如下经典例子:不同类可能有相同的动作(方法)和属性
class Duck():
    def walk(self):
         print('I walk like a duck')
    def swim(self):
         print('i swim like a duck')
 
class Person():
    def walk(self):
       print('this one walk like a duck') 
    def swim(self):
       print('this man swim like a duck')

例1

class Animal:
     pass
 class Dog(Animal):
     def say(self):
         print('汪汪汪')
 class Cat(Animal):
     def say(self):
         print('喵喵喵')
 def animal_say(obj):
 obj.say()
 dog=Dog()
 cat=Cat()
 animal_say(dog)

例2,同一类事物,如饭馆,有不同的菜品

class Fanguan:
     pass
 class Yuxiangrousi(Fanguan):
     def caidan(self):
         print('鱼香肉丝')
 class Gongbaojiding(Fanguan):
     def caidan(self):
         print('宫保鸡丁')
 class Qingjiaotudousi(Fanguan):
     def caidan(self):
         print('青椒土豆丝')
 def fuwuyuan(obj):
     obj.caidan()
 guke1=Yuxiangrousi()
 guke2=Gongbaojiding()
 guke3=Qingjiaotudousi()
 fuwuyuan(guke3)

例3:写一个猜数字游戏,需求如下:随机生成一个100以内的整数,让用户猜,如果猜对了,提示回答正确, 游戏结束 如果猜错了, 提示过大或过小, 最多允许猜7次

from random import randint
 answer=randint(1,100)  # 在1-100之间生成一个整数,包含边界值
 for i in range(7):
     input1=input('请输入一个数字:  ')
     if not input1.isdigit():
         print('您输入的不是数字,游戏结束')
         break
     else:
         input1=int(input1)  #将用户输入的字符串型数字转为真正的数字
         if input1==answer:
             print('回答正确,游戏结束')
             break
         elif input1>answer:
             print('数字过大')
         else:
             print('数字过小')

例4:写一个三角形的类

class Triangle:
     def __init__(self,a,b,c):
         self.a=a
         self.b=b
         self.c=c
     def permiter (self):
         if self.a+self.b<=self.c or self.a+self.c<=self.b or self.b+self.c<=self.a:
             return '无法构成三角形,忽略周长'
         else:
             return self.a+self.b+self.c
     def area(self):
         if self.a + self.b <= self.c or self.a + self.c <= self.b or self.b + self.c <= self.a:
             return '无法构成三角形,忽略面积'
         else:
             p=(self.a+self.b+self.c)/2
             return (p*(p-self.a)*(p-self.b)*(p-self.c))**0.5
 sjx=Triangle(3,4,5)
 print(sjx.permiter ())
 print(sjx.area())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

媛媛要加油呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值