Python编程:09- 面向对象--反射(单例模式)&继承&重
2023-06-27 本文已影响0人
小小一颗卤蛋
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())