Python面向对象(二)
一.组合
组合指的是某一个对象拥有一个属性,该属性的值是另一个对象
如下:
class Foo: pass class Bar(): pass obj = Foo() obj.attr = Bar()
通过为某一个对象添加属性(属性的值为另一个对象)的方式,可以间接地将两个类关联/整合到一起,从而减少类与类之间的代码冗余
案例如下:
class Person: def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class Student(Person): def __init__(self, name, age, sex, score=0): super(Student, self).__init__(name, age, sex) self.score = score self.courses = [] def study(self): print('%s正在学习' % self.name) def all_course_info(self): for obj in self.courses: obj.show() class Teacher(Person): def __init__(self, name, age, sex, level): super().__init__(name, age, sex) self.level = level self.courses = [] def work(self): print('%s正在去上课的路上' % self.name) def all_course_info(self): for obj in self.courses: obj.show() class Course: def __init__(self, c_name, c_price, c_period): self.c_name = c_name self.c_price = c_price self.c_period = c_period def show(self): print('课程名:%s 课程价格:%s 课程周期:%s' % (self.c_name, self.c_price, self.c_period)) python = Course('python全栈开发', 1000, '6个月') linux = Course('linux', 500, '3个月') stu1 = Student('Yven', 18, 'male') stu1.courses.append(python) stu1.courses.append(linux) stu1.all_course_info() tea1 = Teacher('Hwt', 18, 'female', 10) tea1.courses.append(python) tea1.all_course_info()
二.多态
多态指的是同一种/类事物的不同形态,不同的子类对象调用相同的父类方法,产生不同的执行结果,多态可以增加代码的灵活度,以继承和重写父类方法为前提,是调用方法的技巧,不会影响到类的内部手机
案例如下:
import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def speak(self): pass @abc.abstractmethod def run(self): pass class Person(Animal): def speak(self): print('hello') def run(self): pass class Dog(Animal): def speak(self): print('汪汪汪') def run(self): pass class Pig(Animal): def speak(self): print('oooo') def run(self): pass obj1 = Person() obj2 = Dog() obj3 = Pig() obj1.speak() obj2.speak() obj3.speak()
三.封装
封装顾名思义就是封与装
封指的是将存放于名称空间中的名字给藏起来,这种隐藏对外不对内
装指的是往容器/名称空间里存入名字
案例如下:
class Foo: __x=111 # _Foo__x __y=222 # _Foo__y def __init__(self,name,age): self.__name=name self.__age=age def __func(self): #_Foo__func print('func') def get_info(self): print(self.__name,self.__age,self.__x) #print(self._Foo__name,self._Foo__age,self._Foo__x) # print(Foo.__x) # print(Foo.__func) # print(Foo.__dict__) # print(Foo._Foo__x) # print(Foo._Foo__y) # Foo.__z=333 # print(Foo.__dict__) # print(Foo.__z) obj=Foo('egon',18) # print(obj.__dict__) # print(obj.__name) # print(obj.__age) # obj.get_info() obj.__sex='male' # print(obj.__dict__) # print(obj.__sex) # obj.get_info() # 1. __开头的属性到底如何实现的隐藏? # 2. 如何实现的对外隐藏,对内不隐藏 class Foo: def __f1(self): #_Foo__f1 print('Foo.f1') def f2(self): print('Foo.f2') self.__f1() #obj._Foo__f1() class Bar(Foo): def __f1(self): # _Bar__f1 print('Bar.f1') obj=Bar() # obj.f2() ''' Foo.f2 Bar.f1 ''' # 封装数据属性:将数据属性隐藏起来,类外就无法直接操作属性,需要类内开辟一个接口来外部的使用可以间接地操作属性,可以在接口内定义任意的控制逻辑, # 从而严格控制使用对属性的操作 class People: def __init__(self,name,age): self.__name=name self.__age=age def tell_info(self): print('<name:%s age:%s>' %(self.__name,self.__age)) def set_info(self,name,age): if type(name) is not str: print('名字必须是str类型傻叉') return if type(age) is not int: print('年龄必须是int类型傻叉') return self.__name=name self.__age=age obj=People('egon',18) # obj.tell_info() # obj.set_info('EGON',19) # obj.set_info(123,19) obj.set_info('EGON','18') obj.tell_info() # 封装函数属性:隔离复杂度 class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a=ATM() a.withdraw()
在类内定义的属性前加__开头就可以实现封装的对外不对内的隐藏
总结:
1.__开头的属性实现的隐藏仅仅只是一种语法意义上的变形,并不会真的限制类外部的访问
2.该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性并不会变形
3.如果父类不想让子类覆盖自己的属性,可以在属性前加__开头
四.property
property装饰器是用来将类内的函数属性伪装成数据属性
案例如下:
class People: def __init__(self,name,weight,height): self.name=name self.weight=weight self.height=height @property def bmi(self): return self.weight / (self.height ** 2) obj=People('egon',80,1.83) obj.height=1.85 obj.weight=75 print(obj.bmi()) print(obj.bmi)
了解内容:
class People: def __init__(self,name): self.__name=name @property def name(self): return '<名字:%s>' %self.__name @name.setter def name(self,obj): if type(obj) is not str: print('name必须为str类型') return self.__name=obj @name.deleter def name(self): # print('不让删') del self.__name obj=People('egon') # print(obj.name) # obj.name='EGON' # obj.name=123 # print(obj.name) del obj.name print(obj.__dict__)