面向对象(中)
一、类的构造方法
init()构造方法
1)调用时间:在对象被实例化时被程序自动调用
2)作用:用于对象创建时初始化
3)书写格式:init前后分别是两个下划线
4)程序不显示定义init方法,则程序默认调用一个无参init方法
class Dog:def __init__(self):print("我是构造方法,在创建对象时自动调用")def eat(self):print("正在吃骨头...")def drink(self):print("正在喝水....")wangcai = Dog()print("------------")wangcai.eat()wangcai.drink()
运行结果:
我是构造方法,在创建对象时自动调用------------正在吃骨头...正在喝水....
5)对象创建过程
6)在init()构造方法中初始化对象属性
class Dog:def __init__(self, gender, variety, name):self.gender = genderself.variety = varietyself.name = name# 获取对象属性,并打印出来def get_pro(self):print("gender:{},variety:{},name:{}".format(self.gender, self.variety, self.name))wangcai = Dog("male","golden","wangcai")yuanbao = Dog("female","husky","yuanbao")wangcai.get_pro()yuanbao.get_pro()
运行结果:
gender:male,variety:golden,name:wangcaigender:female,variety:husky,name:yuanbao
分别调用,互不干扰
注:self参数必须是第一个参数
对象创建过程:
二、类的访问权限
1、修改对象属性的方法
1)方法1:对象变量名.属性 = 新值
方法1存在的问题:
(1)可能修改的属性值不合法
(2)在类的外部可以随意修改类的内部属性
2)方法2:对象变量名.内部修改属性方法
class Dog:def __init__(self,gender,variety,name,age):self.gender = genderself.variety = varietyself.name = nameself.age = age# 获取对象属性,并打印出来def get_pro(self):print("gender:{},variety:{},name:{},age:{}".format(self.gender, self.variety, self.name, self.age))def set_pro(self, **kwargs):if "gender" in kwargs:self.gender = kwargs["gender"]elif "age" in kwargs:if kwargs["age"] < 0 or kwargs["age"] > 20:print("非法年龄")else:self.age = kwargs["age"]wangcai = Dog("male","golden","wangcai",5)#修改对象属性,方法1直接修改wangcai.age = 100 #数值可能不合法,但仍可以修改wangcai.get_pro()#方法2:通过内部方法修改属性wangcai.set_pro(age=10)wangcai.get_pro()
运行结果:
gender:male,variety:golden,name:wangcai,age:100gender:male,variety:golden,name:wangcai,age:10
2、私有属性
1)定义:__私有变量名
在变量名前加两个下划线:self.__private_attrs
2)只能在类内部使用,类外部不能访问,否则报错
例1:
class Dog:def __init__(self,gender,variety,name,age):self.gender = genderself.variety = varietyself.name = nameself.__age = age# 获取对象属性,并打印出来def get_pro(self):print("gender:{},variety:{},name:{},age:{}".format(self.gender, self.variety, self.name, self.__age))def set_pro(self, **kwargs):if "gender" in kwargs:self.gender = kwargs["gender"]elif "age" in kwargs:if kwargs["age"] < 0 or kwargs["age"] > 20:print("非法年龄")else:self.__age = kwargs["age"]wangcai = Dog("male","golden","wangcai",5)#方法1,无法修改私有属性值wangcai.age = 100wangcai.get_pro()#方法2,可以通过内部的方法修改私有属性值wangcai.set_pro(age=10)wangcai.get_pro()
运行结果:
gender:male,variety:golden,name:wangcai,age:5gender:male,variety:golden,name:wangcai,age:10
例2:
class Counter:__privateCount = 0 # 私有变量publicCount = 0 # 公有变量def count(self):self.__privateCount += 1self.publicCount += 1print(self.__privateCount)counter = Counter()counter.count()counter.count()print(counter.publicCount)print(counter.__privateCount) #会报错,类外部不能访问
3、私有方法
1)只能在类内部调用,在类的外部无法调用
2)定义私有方法:在方法名前添加两个下划线
3)类内部调用私有方法:self.__private_methods
#私有方法的使用class Comrade:#私有方法def __send_message(self):print("消息已经向上级汇报")def answer_secret(self,secret):if secret == "芝麻开门":print("接头成功!") self.__send_message()#调用私有方法else:print("接头失败!")comrade = Comrade()comrade.answer_secret("芝麻开门")
运行结果:
接头成功!消息已经向上级汇报
三、继承和多态
在程序中,继承描述的时类中类型与子类型之间的所属关系
1、单继承
1)子类继承一个父类,在定义子类时,小括号中写父类的类名
2)父类的非私有属性、方法会被子类继承
class Animal:def eat(self):print("----吃----")def drink(self):print("----喝----")def run(self):print("----跑----")class Dog(Animal):def hand(self):print("------握手-----")wangcai = Dog()#调用从父类继承的方法wangcai.eat()wangcai.drink()wangcai.run()#调用自身的方法wangcai.hand()
运行结果:
----吃--------喝--------跑----------握手-----
3)子类中方法的查找方式:先查找子类中对应的方法,如果找不到,再到父类中查找
4)子类可以继承父类的属性和方法,也可以继承父类的父类的非私有属性和方法,以次类推
class Animal:def eat(self):print("----吃----")def drink(self):print("----喝----")def run(self):print("----跑----")class Dog(Animal):def hand(self):print("------握手-----")class GoldenDog(Dog):def guid(self):print("我能导航!")golden = GoldenDog()golden.guid()golden.hand()golden.run()
运行结果:
我能导航!------握手---------跑----
5)在子类中调用父类的方法:ClassName.methodname(self)
class Animal:def run(self):print("----跑----")class Dog(Animal):def hand(self):Animal.run(self)print("------握手-----")wangcai = Dog()wangcai.hand()
运行结果:
----跑----------握手-----
6)重写父类方法:
(1)子类对父类允许访问的方法的实现过程进行重新编写
(2)在子类中定义与父类同名的方法
(3)优点:子类可以根据需要,定义合适的方法实现逻辑
class Animal:def run(self):print("----跑----")class Dog(Animal):#父类方法重写def run(self):print("摇着尾巴跑")duoduo = Dog()duoduo.run()
运行结果:
摇着尾巴跑
7)如果在子类中没有定义init构造方法,则自动调用父类的init构造方法,如果在子类中定义了init构造方法,则不会调用父类的构造方法
class Animal:def __init__(self):print("---animal构造方法----")def run(self):print("----跑----")class Dog(Animal):def __init__(self):print("dog构造方法")def run(self):print("摇着尾巴跑")duoduo = Dog()duoduo.run()
运行结果:
dog构造方法摇着尾巴跑
2、多继承
1)object类是所有类的基类,在定义类的时候不需要显示的在括号中表明继承自object类
2)多继承:一个子类可以继承多个父类
3)多继承定义方式:在类名后的括号中添加需要继承的多个类名
4)多继承中,如果多个类中有同名的方法,子类调用查找方法的顺序是按照小括号内继承父类的顺序从左到右顺序查找,第一个匹配方法名的父类方法将会被调用
class AI:def face_recongnition(self):print("人脸识别")def data_handle(self):print("AI数据处理")class BigData:def data_analysis(self):print("数据分析")def data_handle(self):print("BigData数据处理")class Python(BigData,AI):def operation(self):print("自动化运维")class Python2(AI,BigData):def operation(self):print("自动化运维2")py = Python()py2 = Python2()py.face_recongnition()py.data_analysis()py.operation()py.data_handle()py2.data_handle()print(Python.__mro__)print(Python2.__mro__)
运行结果:
人脸识别数据分析自动化运维BigData数据处理AI数据处理(<class '__main__.Python'>, <class '__main__.BigData'>, <class '__main__.AI'>, <class 'object'>)(<class '__main__.Python2'>, <class '__main__.AI'>, <class '__main__.BigData'>, <class 'object'>)
注:在父类起方法名的时候尽量避免同名,避免制造麻烦
3、多态
一个抽象类有多个子类,不同的类表现出多种形态
class Animal:def eat(self):print("Animal正在吃饭")class Dog(Animal):def eat(self):print("Dog正在吃饭")class Cat(Animal):def eat(self):print("Cat正在吃饭")def show_eat(obj):obj.eat()wangcai = Dog()show_eat(wangcai)tom = Cat()show_eat(tom)
运行结果:
Dog正在吃饭Cat正在吃饭
