Python面向对象

三种编程方法论

  • 面向过程:把复杂的任务一步一步分解成简单的任务。
  • 函数式编程:思想上接近于数学运算,根据某种方式,根据方式得出的结果。
  • 面向对象编程:一种编程方式,须要使用“类”和“对象”来实现,其实就是对“类”和“对象的”使用

软件质量属性

软件质量属性包含:成本,性能,可靠性,安全性,可维护性,可移植性,可伸缩性,可扩展性等python

面向过程

  • 概念:核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么......,把这个大的问题分解成不少个小问题或子过程,这些子过程在执行的过程当中继续分解,直到小问题足够简单到能够在一个小步骤范围内解决。
  • 优势:复杂的问题流程化,进而简单化
  • 缺点:扩展性极差
  • 应用场景:通常用于那些功能一旦实现以后就不多须要改变的场景, 若是你只是写一些简单的脚本,去作一些一次性任务,用面向过程的方式是极好的,著名的例子有Linux內核,git,以及Apache HTTP Server等。但若是你要处理的任务是复杂的,且须要不断迭代和维护 的, 那仍是用面向对象最方便了。

面向对象编程

  • 概念:核心是“对象”二字,对象就是特征与技能的结合体。
  • 优势:可扩展性高
  • 缺点:编程的复杂度高,易出现过分设计的问题
  • 应用场景:应用于需求常常变化的软件中,通常需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。

1、名词解释

  • :一个类便是对一类拥有相同属性的对象的抽象、蓝图、原型、模板。在类中定义了这些对象的都具有的属性(variables(data))、共同的方法
  • 属性:人类包含不少特征,把这些特征用程序来描述的话,叫作属性,好比年龄、身高、性别、姓名等都叫作属性,一个类中,能够有多个属性
  • 方法:人类不止有身高、年龄、性别这些属性,还能作好多事情,好比说话、走路、吃饭等,相比较于属性是名词,说话、走路是动词,这些动词用程序来描述就叫作方法。
  • 实例(对象):一个对象便是一个类的实例化后实例,一个类必须通过实例化后方可在程序中调用,一个类能够实例化多个对象,每一个对象亦能够有不一样的属性,就像人类是指全部人,每一个人是指具体的对象,人与人以前有共性,亦有不一样
  • 实例化:把一个类转变为一个对象的过程就叫实例化 就是类名+括号,就是在执行类的__init__()方法
  • 构造方法:__init__(...)被称为 构造方法或初始化方法,在例实例化过程当中自动执行,目的是初始化实例的一些属性。每一个实例经过__init__初始化的属性都是独有的
  • 析构方法(解构方法):__del__(self)被称为 析构方法或解构方法,实例在内存中被删除时,会自动执行这个方法。

2、类和对象

  • 类中能够有任意python代码,这些代码在类定义阶段便会执行
  • 于是会产生新的名称空间,用来存放类的变量名与函数名,能够经过 类名.__dict__查看
  • 对于经典类来讲咱们能够经过该字典操做类名称空间的名字(新式类有限制),但python为咱们提供专门的.语法
  • 点是访问属性的语法,类中定义的名字,都是类的属性
  • isinstance(obj,cls)检查obj是不是类 cls 的对象
  • 类的两种用法:实例化和属性引用(类的属性就两种:变量和函数)
  • 对象也叫实例只有一种用法:属性引用,就对象自己而言它只有数据属性
country='American'
def study():
    print('study english')

class Student():
    country = 'China'
    def __init__(self, ID, NAME, SEX, PROVINCE,country):
        self.id = ID
        self.name = NAME
        self.sex = SEX
        self.province = PROVINCE
        self.country = country

    def search_score(self):
        print('全局的',country)
        study() #全局的

        print('类里的', Student.country)
        Student.study(self) #类里的

        print('对象的', self.country) #对象有就从自身找,没有就从类中找
        self.study() #

    def study(self):
        print('study',self.country)

s1 = Student('3718818181', 'alex', 'female', 'shanxi','Singapore')
s1.search_score()

"""
全局的 American
study english
类里的 China
study Singapore
对象的 Singapore
study Singapore
"""
类中调用属性

3、__init__方法

  • 为对象初始化本身独有的特征
  • 该方法内能够有任意的python代码
  • 必定不能有返回值*****

4、属性查找

在obj.name会先从obj本身的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常git

  • 类有两种属性:数据属性和函数属性
  • 类的数据属性是全部对象共享的
  • 类的函数属性是绑定给对象用的
class A:
    def fa(self):
        print('from A')
    def test(self):
        self.fa()

class B(A):
    def fa(self):
        print('from B')

b=B()
b.test()  #from B
"""
从本身找b.test(),没有找类B,也没有找类A,找到后执行self.fa(),
self指的是b对象,而后又从本身找fa(),没有就去类B中找fa(),找到了 因此打印  from B
"""

class C:
    def __fa(self):  #_C__fa
        print('from C')
    def test(self):
        self.__fa()   #slef._C__fa   __在定义阶段就会变形

class D(C):
    def __fa(self):  #_D__fa
        print('from D')

d=D()
d.test()  #from C
"""
__不能被子类继承和覆盖
"""
属性查找顺序

5、特性1:封装

封装在于明确区份内外, 类的实现者不须要让类的调用者知道具体的实现过程,隔离了复杂度,同时也提高了安全性,类的实现者能够修改封装内的东西而不影响外部调用者的代码。编程

一、构造方法和类自己的包裹

使用构造方法将属性封装到某个具体对象中,而后经过对象直接或者self间接获取被封装的属性,类自己就是一种封装的体现,它将数据与专门操做该数据的功能整合到一块儿。安全

二、__双下划线属性隐藏

  • 在python中用双下划线开头的方式将属性隐藏起来,设置成私有的
  • 类中全部双下划线开头的名称如__x都会在类定义时自动变造成:_类名__x的形式
  • 变形的过程只在类的定义时发生一次,在定义后的赋值操做,不会变形
  • 在继承中,父类若是不想让子类覆盖本身的方法,能够将方法定义为私有的

三、装饰器@property也有封装的思想

  • @property 类的静态属性:
    1. 将一个类的函数定义成特性之后,对象再去使用的时候obj.mbi,根本没法察觉本身的mbi是执行了一个函数而后计算出来的,
    2. @property这种特性的使用方式遵循了统一访问的原则
  • @classmethod
    1. 把一个方法绑定给类,会把类自己当作第一个参数自动传给绑定到类的方法
    2. 类的绑定方法
  • @staticmethod
    1. 被staticmethod装饰器修饰过的方法,都是解除绑定的方法,实际上就函数:就没有自动传值功能了
    2. 解除绑定的方法
  • 凡是定义在类的内部,而且没有被任何装饰器修饰过的方法,都是绑定方法:有自动传值功能
import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

    @property  #被@property装饰的方法,调用的时候能够不用加括号,area=property(area)
    def area(self):
        return math.pi * self.radius**2 #计算面积

    @property
    def perimeter(self):
        return 2*math.pi*self.radius #计算周长


c=Circle(3)
print(c.area)
print(c.perimeter)
@property
#被property装饰的属性会优先于对象的属性被使用,只有在属性sex定义property后才能定义sex.setter,sex.deleter
class People:
    def __init__(self,name,SEX):
        self.name=name
        # self.__sex=SEX  #这不调用@sex.setter  def sex(self,value):方法  由于设置的是__sex 不是 sex,或者说__sex没有被@property装饰
        self.sex=SEX      #①由于sex被@property装饰,因此self.sex=SEX是去找@sex.setter  def sex(self,value): 方法,而不是给对象赋值
    @property
    def sex(self):
        return self.__sex #p1.__sex
    @sex.setter
    def sex(self,value):
        print('...')
        if not isinstance(value,str):
            raise TypeError('性别必须是字符串类型')
        self.__sex=value         #② male给了value ,  self.__sex='male'
    @sex.deleter                      #del p1.sex的时候调用
    def sex(self):
        del self.__sex #del p1.__sex

p1=People('alex','male')  #会调用 @sex.setter  def sex(self,value): 方法是由于__init__中 self.sex=SEX 是给sex设置值了
p1.sex='female' #会调用@sex.setter  def sex(self,value): 方法
del p1.sex
print(p1.sex) #AttributeError: 'People' object has no attribute '_People__sex'
@property @属性.setter @属性.deleter
import time
class Date:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

    @classmethod  #把一个方法绑定给类:类.绑定到类的方法(),会把类自己当作第一个参数自动传给绑定到类的方法
    def now(cls): #用Date.now()的形式去产生实例,该实例用的是当前时间
        t=time.localtime() #获取结构化的时间格式
        obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建实例而且返回
        return obj

    @classmethod
    def tomorrow(cls):#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间
        t=time.localtime(time.time()+86400)
        return cls(t.tm_year,t.tm_mon,t.tm_mday)

class EuroDate(Date):
    def __str__(self):
        return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day)

e1=EuroDate.now()
print(e1)

e1=EuroDate(1,1,1)
print(e1)

"""
年:2019,月:3,日:17
年:1,月:1,日:1
"""
@classmethod
import time
class Date:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

    @staticmethod
    def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间
        t=time.localtime() #获取结构化的时间格式
        obj=Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例而且返回
        return obj

    @staticmethod
    def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间
        t=time.localtime(time.time()+86400)
        return Date(t.tm_year,t.tm_mon,t.tm_mday)


d1=Date.now()
print(d1.year,d1.month,d1.day)

d2=Date.tomorrow()
print(d2.day)
@staticmethod

6、特性2:继承

继承是一种建立新类的方式,新建的类能够继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。解决了代码重复的问题服务器

一、继承顺序

  • python会计算出一个方法解析顺序(mro)列表,这个mro列表就是一个简单的全部基类的线性顺序列表 F.mro()等同于F.__mro__ 注意只有新式类才有这个方法
  • 子类会先于父类被检查
  • 多个父类会根据它们在列表中的顺序被检查
  • 若是对下一个类存在两个合法的选择,选择第一个父类
  • 经典类的深度优先查找和新式类的广度优先查找

二、子类中调用父类的方法

  • 方法一:父类名.父类方法() 父类名.__init__(self,name,speed,load,power)
  • 方法二:【super只能用于新式类】super(本身的类,self).父类的函数名字
    python3中写法:super().__init__(name,speed,load,power)
    python2中写法:super(Subway,self).__init__(name,speed,load,power)
  • 两者使用哪种均可以,但最好不要混合使用,注意区分参数self
  • 这两种方式的区别是:方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,而且即便没有直接继承关系,super仍然会按照mro继续日后查找
  • super(Subway,self) 就至关于实例自己 在python3中super()等同于super(Subway,self)
  • issubclass(sub, super)检查sub类是不是 super 类的派生类

三、经典类与新式类

  • 只有在python2中才分新式类和经典类,python3中统一都是新式类
  • 在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
  • 在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
  • 在python3中,不管是否继承object,都默认继承object,即python3中全部类均为新式类
  • A.__bases__ 或者 A.__mor__查看类A的继承。mor()方法只在新式类中有

四、继承和抽象(先抽象再继承)

  • 抽象即提取相似的部分。
  • 基类就是抽象多个类共同的属性获得的一个类。

五、派生

  • 派生就是子类在继承父类的基础上衍生出新的属性。
  • 子类中独有的,父类中没有的或子类定义与父类重名的属性,那么在调用子类的这个属性时就以子类本身的为准。
  • 子类也叫派生类。

7、特性3:多态

  • 多态:指的是一类事物有多种形态,好比动物有多种形态:人,狗,猪
  • 多态性:指在不考虑实例类型的状况下使用实例,多态性分为静态多态性和动态多态性,想一想len 函数的使用
  • 静态多态性:如任何类型均可以用运算符+进行运算
  • 动态多态性:
  • 实现:不一样的类先继承基类,而后不一样类的实例调用相同的方法(这个相同的方法是从基类那继承来的)
  • 做用:增长了程序的灵活性和可扩展性,(使用者都是同一种形式去调用)
#多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
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.run()

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


# peo1.run()
# pig1.run()


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

func(peo1)
func(pig1)
多态性

其余补充

1、类的组合

软件重用的重要方式除了继承以外还有另一种方式,即:组合 组合指的是,在一个类中以另一个类的对象做为数据属性,称为类的组合ide

当类之间有显著不一样,而且较小的类是较大的类所须要的组件时,用组合比较好函数式编程

class Teacher:
    def __init__(self,name,sex,course):
        self.name=name
        self.sex=sex
        self.course=course
class Student:
    def __init__(self,name,sex,course):
        self.name=name
        self.sex=sex
        self.course=course
class Course:
    def __init__(self,name,price,peroid):
        self.name=name
        self.price=price
        self.period=peroid
python_obj=Course('python',15800,'7m')
t1=Teacher('egon','male',python_obj)
s1=Student('cobila','male',python_obj)

print(s1.course.name)
print(t1.course.name)
组合

2、抽象类(接口与归一化设计)

一、接口

  • 接口:接口提取了一群类共同的函数,能够把接口当作一个函数的集合,而后让子类去实现接口中的函数。
  • 做用:归一化设计,限制实现接口的类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现。
  • hi boy,给我开个查询接口。。。此时的接口指的是:本身提供给使用者来调用本身功能的方式\方法\入口

二、归一化

  • 归一化:就是只要是基于同一个接口实现的类,那么全部的这些类产生的对象在使用时,从用法上来讲都同样。
  • 好处:
    1. 归一化让使用者无需关心对象的类是什么,只须要的知道这些对象都具有某些功能就能够了,这极大地下降了使用者的使用难度。
    2. 归一化使得高层的外部使用者能够不加区分的处理全部接口兼容的对象集合
class Animal:
    def run(self):
        raise AttributeError('子类必须实现这个方法')
    def speak(self):
        raise AttributeError('子类必须实现这个方法')

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

    def speak(self):
        print('说话')

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


# peo1=People()
# pig1=Pig()
#
# peo1.run()
# pig1.run()
接口与归一化设计

三、抽象类

  • 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
  • 类是从一堆对象中抽取相同的内容而来的,抽象类是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
  • 抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。
import abc
#抽象类:本质仍是类,与普通类额外的特色的是:加了装饰器的函数,子类必须实现他们
class Animal(metaclass=abc.ABCMeta):
    tag='123123123123123'
    @abc.abstractmethod
    def run(self):
        pass
    @abc.abstractmethod
    def speak(self):
        pass

class People(Animal):
    def run(self):
        pass

    def speak(self):
        pass

peo1=People()
print(peo1.tag)
抽象类

四、抽象类与接口

  • 抽象类的本质仍是类,指的是一组类的类似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的类似性。
  • 抽象类是一个介于类和接口之间的一个概念,同时具有类和接口的部分特性,能够用来实现归一化设计

3、类中定义的函数分红两大类

一、绑定方法(绑定给谁,谁来调用就自动将它自己看成第一个参数传入)

  1. 绑定到类的方法:用classmethod装饰器装饰的方法。
    • 为类量身定制
    • 类.bound_method(),自动将类看成第一个参数传入
    • (其实对象也可调用,但仍将类看成第一个参数传入)
  2. 绑定到对象的方法:没有被任何装饰器装饰的方法。
    • 为对象量身定制
    • 对象.bound_method(),自动将对象看成第一个参数传入
    • (属于类的函数,类能够调用,可是必须按照函数的规则来,没有自动传值那么一说)

二、非绑定方法:用staticmethod装饰器装饰的方法

  • 不与类或对象绑定,类和对象均可以调用,可是没有自动传值那么一说。就是一个普通工具而已
  • 注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,无论谁来调用,都没有自动传值一说

4、反射

经过字符串的形式操做对象相关的属性。python中的一切事物都是对象(均可以使用反射)函数

  • hasattr(object,name) 判断object中有没有一个name字符串对应的方法或属性
  • getattr(object, name, default=None)
  • setattr(x, y, v)
  • delattr(x, y)
import sys
def add():
    print('add')

def change():
    print('change')

def search():
    print('search')

def delete():
    print('delete')

this_module=sys.modules[__name__] #获取当前模块
while True:
    cmd=input('>>:').strip()
    if not cmd:continue
    if hasattr(this_module,cmd):
        func=getattr(this_module,cmd)
        func()

#多分支判断方式1:
# func_dic={
#     'add':add,
#     'change':change,
#     'search':search,
#     'delete':delete
# }

#
# while True:
#     cmd=input('>>:').strip()
#     if not cmd:continue
#     if cmd in func_dic:
#         func=func_dic.get(cmd)
#         func()

#多分支判断方式2:
# class Service:
#     def run(self):
#         while True:
#             inp = input('>>: ').strip()  # cmd='get a.txt'
#             cmds = inp.split()  # cmds=['get','a.txt']
#             if hasattr(self, cmds[0]):
#                 func = getattr(self, cmds[0])
#                 func(cmds)
#
#     def get(self, cmds):
#         print('get.......', cmds)
#
#     def put(self, cmds):
#         print('put.......', cmds)
#
# obj = Service()
# obj.run()
反射的用途1
#ftpclient.py    
class FtpClient:

    'ftp客户端,可是还么有实现具体的功能'
    def __init__(self,addr):
        print('正在链接服务器[%s]' %addr)
        self.addr=addr
    def test(self):
        print('test')
    def get(self):
        print('get------->')
        
#ftpserver.py        
#服务端同窗能够不用非等着客户端同窗写完代码才去实现
import ftpclient

f1=ftpclient.FtpClient('192.168.1.1')
if hasattr(f1,'get'): #有就执行没有就执行其余逻辑
    func=getattr(f1,'get')
    func()
else:
    print('其余逻辑')
反射用途2:实现可插拔机制
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
# 先定义类 后产生对象
class Animal:
    def eat(self):
        print('is eating')
 
 
class Student(Animal):  # 继承,可继承多个,用mro()查看继承关系
    school = 'Peking University'  # 类的数据属性
    count = 0
 
    def __init__(self, name, age):  # 类的函数属性,也就是对象的绑定方法()
        self.name = name
        self.age = age
        Student.count += 1
 
    def learn(self):
        print('%s is learning' % self.name)
 
    def eat(self):  # 重写父类方法
        print('Wash your hands before eating')  # 加入本身新功能
        # Peo2.eat(self)                             #重用父类的方法
        # super(Student,self).eat()                  #重用父类的方法
        super().eat()  # 重用父类的方法  super是按照mro的顺序查找
 
"""
类:
一、类的数据属性是全部对象共享的,id都同样
二、类的函数属性是绑定给对象用的,obj.method称为绑定方法,绑定到不一样的对象是不一样的绑定方法,对象调用绑定方式时,会把对象自己看成第一个传入,传给self
    (绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self能够是任意名字,可是约定俗成地写出self。 )
三、__init__方法
    (1)、该方法内能够有任意的python代码
    (2)、必定不能有返回值
     
继承:
"""
print(issubclass(Student, Animal))# 检查Student类是不是Animal类的派生类
 
#
Student.country = 'China'
#
del Student.country
#
Student.school = 'Tsinghua University'
#
print(Student.__dict__)  # 查看类的名称空间
print(Student.school)
print(Student.learn)
 
print(Student.__mro__)  # 查看类的继承关系
print(Student.__bases__)  # 查看类的父类
 
"""
对象:
属性查找顺序:在obj.name会先从obj本身的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常
"""
stu = Student('tom', 18)  # 实例化一个对象
print(isinstance(stu,Student))  #obj是不是类 cls 的对象
 
#
stu.gender = 'male'
#
del stu.gender
#
stu.age = 28
#
print(stu.__dict__)
print(stu.name)
stu.eat()
 
"""
super 按照mro的顺序查找
"""
class A:
    def f1(self):
        print('from A')
        super().f1()
class B:
    def f1(self):
        print('from B')
class C(A, B):
    pass
print(C.mro())
# [<class '__main__.C'>,
# <class '__main__.A'>,
# <class '__main__.B'>,
# <class 'object'>]
c = C()
c.f1()  # 打印  from A   from B
 
"""
封装:类的实现者不须要让类的调用者知道具体的实现过程
"""
 
"""
__私有属性,私有方法 (类的定义极端就已经变形了)
这种变形的特色:
    一、在类外部没法直接obj.__AttrName
    二、在类内部是能够直接使用:obj.__AttrName
    三、子类没法覆盖父类__开头的属性
    四、在定义阶段就会变形,也就是说__开头的属性(变量和函数)不能被子类继承 由于在定义阶段__属性名就变成了_父类名__属性名。
"""
 
class A:
    def __foo(self):  # _A__foo
        print('A.foo')
 
    def bar(self):
        print('A.bar')
        self.__foo()  # self._A__foo()
 
 
class B(A):
    def __foo(self):  # _B__foo
        print('B.foo')
 
 
b = B()
b.bar()
 
"""
@property
类的静态属性,类方法,类的静态方法
在类内部定义的函数,分为两大类:
    一:绑定方法:绑定给谁,就应该由谁来调用,谁来调用就回把调用者看成第一个参数自动传入
        绑定到对象的方法:在类内定义的没有被任何装饰器修饰的
 
        绑定到类的方法:在类内定义的被装饰器classmethod修饰的方法
 
    二:非绑定方法:没有自动传值这么一说了,就类中定义的一个普通工具,对象和类均可以使用
        非绑定方法:不与类或者对象绑定
"""
 
import hashlib, time
class Teacher:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height
        self.id = self.create_id()
 
    @property  # 类的静态属性@property   封装的部分体现
    def bmi(self):
        return self.weight / (self.height ** 2)
 
    @classmethod  # 绑定到类的方法
    def talk(cls):
        print('is talking')
 
    @staticmethod  # 非绑定方法 类的静态方法,就是一个普通工具
    def create_id():
        m = hashlib.md5(str(time.time()).encode('utf-8'))
        return m.hexdigest()
 
    def play(self):  # 绑定到对象的方法
        print('is playing')
 
 
t = Teacher('jack', 80, 1.8)
print(t.bmi)
print(t.id)
 
"""
多态:
不考虑对象的类型,直接使用对象,也就是不一样类的实例调用相同的方法,实现的过程不同。
多态怎么来的?
1,不一样的类先继承基类,
2,而后不一样类的实例调用相同的方法(这个相同的方法是从基类那继承来的)
 
抽象类:
本质仍是类,于普通类不同的是,加了装饰器的函数,子类必须实现他们,也就是抽象类的方法必需要重写
"""
import abc
 
class People(metaclass=abc.ABCMeta):  # 抽象类,只能被继承,不能被实例化
    @abc.abstractmethod
    def answer(self):
        pass
 
class Chinese(People):
    def answer(self):  # 抽象类的方法必需要重写
        print('用中文答辩')
 
class English(People):
    def answer(self):  # 抽象类的方法必需要重写
        print('use english')
 
chi = Chinese()
eng = English()
 
def ans(obj):        # 相同的调用方式
    obj.answer()
 
ans(chi)            # 相同的调用方式    多态
ans(eng)            # 相同的调用方式
 
 
"""
类的组合:
软件重用的重要方式除了继承以外还有另一种方式,即:组合
组合指的是,在一个类中以另一个类的对象做为数据属性,称为类的组合
"""
class Date:
    def __init__(self, year, mon, day):
        self.year = year
        self.mon = mon
        self.day = day
 
    def tell_info(self):
        print('My birthday is %s-%s-%s' % (self.year, self.mon, self.day))
 
 
d = Date(1986, 6, 26)
stu2 = Student('rose', 88)
stu2.birth = d
stu2.birth.tell_info()
 
"""
反射:经过字符串映射到对象的属性
setattr(obj,'sex','male')
getattr(obj,'namexxx',None)
hasattr(obj,'talk')
delattr(obj,'age')
"""
 
 
class Service:
    def run(self):
        while True:
            inp = input('>>: ').strip()  # cmd='get a.txt'
            cmds = inp.split()  # cmds=['get','a.txt']
            if hasattr(self, cmds[0]):
                func = getattr(self, cmds[0])
                func(cmds)
 
    def get(self, cmds):
        print('get.......', cmds)
 
    def put(self, cmds):
        print('put.......', cmds)
 
 
obj = Service()
# obj.run()
相关文章
相关标签/搜索