python进阶-面向对象编程:类和对象一:抽象类/接口/继承组合/封装/多态

基本过程:

面向对象的程序设计
如何使用类:
1,实例化
2,引用类的特征(变量)和技能(函数)


如何使用类:
1,实例化
2,引用名(类名.变量名,类名.函数名)
3,实例(实例.类变量,实例.绑定类函数名)
# 面向对象的程序设计:
#     找对象---》归纳对象共同的特征与技能,还有每个对象独有的特征---》抽象成类
# 面向对象编程:
#     定义类---》实例化对象

看一个学生类简单例子

class Student:
    country = 'china'

    def __init__(self,ID,NAME,SEX,PROVINCE,score):
        self.id = ID
        self.name = NAME
        self.sex = SEX
        self.province = PROVINCE
        self.score = score

    def search_score(self):
        print(self.name,"的分数是",self.score)

    def study(self):
        print(self.name,"study")

    def walk(self):
        print(self.name,"walk")

    def attack(self):
        print("attack")


#类的变量
print(Student.country)
Student.x=100
print(Student.x)
# china
# 100

#对象,查询,绑定方法的含义就是,谁调用就是作用谁
s1 =Student('37232323','ddamanter','male','广东省',98)
print(s1)#查看对象 <__main__.Student object at 0x1068e82b0>
print("Student.__dict__:",Student.__dict__) #查看类的名称空间,以字典的形式包含类的所有属性:变量和方法以及内置函数
# Student.__dict__: {'study': <function Student.study at 0x1058e2b70>,
# 'x': 100, '__weakref__': <attribute '__weakref__' of 'Student' objects>,
# 'search_score': <function Student.search_score at 0x1058e2a60>,
# '__dict__': <attribute '__dict__' of 'Student' objects>,
# 'walk': <function Student.walk at 0x1058e2bf8>,
# '__init__': <function Student.__init__ at 0x1058e2ae8>,
# '__doc__': None, 'attack': <function Student.attack at 0x1058e2c80>,
# 'country': 'china', '__module__': '__main__'}

print("s1.__dict__:",s1.__dict__) #查看对象的名称空间,以字典的形式包含对象的所有属性
# s1.__dict__: {'score': 98, 'sex': 'male', 'id': '37232323', 'province': '广东省', 'name': 'ddamanter'}

print(s1.country)
print(s1.id)
print(s1.name)
print(s1.sex)
print(s1.province)
print(s1.search_score())
print(s1.study())
print(s1.walk())
# china
# 37232323
# ddamanter
# male
# 广东省
# ddamanter 的分数是 98
# None
# ddamanter study
# None
# ddamanter walk

#增加
s1.height="178cm"
s1.weight="70kg"
s1.age="23"
print(s1.height)
print(s1.weight)
print(s1.age)
# 178cm
# 70kg
# 23



#删除
# del s1.weight
# print(s1.weight)

#修改
s1.height="180cm"
print(s1.height)

一个系统例子

class School:
    tag="school"
    def __init__(self,addr):
        self.addr=addr
        self.teacher_list=[]
        self.course_list=[]


    def admissions(self):
        print("招生")

class Teacher:
    nationality = "china"
    school="peking university"
    def __init__(self,t_name,t_class,t_lesson):
        self.name=t_name
        self._class=t_class
        self.lesson=t_lesson

    def teach(self):
        print("teach",self)

class Student:
    nationality = "china"
    school = "peking university"
    def __init__(self,id,name,sex):
        self.id=id
        self.name=name
        self.sex=sex
        self.course_list=[]

    def search_score(self):
        print("view grades:",self)
    def handin(self):
        pass

class Course:
    def __init__(self,name,price,period):
        self.name=name
        self.price=price
        self.period=period



python_obj=Course('python',20000,'1years')
linux_obj=Course('python',20000,'1years')
s1=Student("001","ada","男")
s1.course_list.append(python_obj)
print("课程名:%s \n课程价格:%s \n课程时间:%s"%(s1.course_list[0].name,s1.course_list[0].price,s1.course_list[0].period))

什么是抽象类以及特点

import abc
# 什么是抽象类:接口只能提供功能的集合,抽象类:本质还是类,
# 与普通类额外特点是:加了装饰器@abc.abstractmethod的函数,所有子类必须实现装饰器的方法

class Animal(metaclass=abc.ABCMeta):
    tag="hello"
    @abc.abstractmethod
    def eat(self):
        pass
    @abc.abstractmethod
    def run(self):
        pass



class People(Animal):
    def eat(self):
        print("peple eat")
    def run(self):
        print("peple run")

基于抽象类的接口与归一化设计

# java 有接口,功能的集合,利用interface ,implament实现,
# python 没有,是模仿,但是一般自己的定义都能用
# 接口提取了一堆函数。是函数的集合
# 接口的意义就是必须实现接口内的所有方法


class Animal:
    def eat(self):
        raise AttributeError("子类必须使用该方法")
    def run(self):
        pass



class People(Animal):
    def eat(self):
        print("peple eat")
    def run(self):
        print("peple run")

  

面向对象编程的三大特点:封装,继承,多态

类的继承和派生以及组合:

为什么要用继承:解决代码重用问题

# 关联类的继承,是一种什么是什么的关系,比如人是动物,用继承
# 非关联类,是一种什么有什么有什么的关系,比如学生有课程,老师有课程,用类之间的组合
# 英雄的昵称,攻击力,生命值 class Hero: def __init__(self,nickname,agressivity,life_value): self.nickname=nickname self.agressivity=agressivity self.life_value=life_value def attack(self): print("Hero attck") # 具体英雄的昵称,攻击力,生命值,台词 class Garen(Hero): def __init__(self,nickname,agressivity,life_value,script): # Hero.__init__(self,nickname,agressivity,life_value) super(Garen,self).__init__(nickname,agressivity,life_value) #以上两种初始化父类的方法都可以,推荐后一种 self.script=script def attack(self,enemy): Hero.attack(enemy) print("%s attck %s"%(self.nickname,enemy)) class Alex(Hero): def __init__(self,nickname,agressivity,life_value,script): Hero.__init__(self,nickname,agressivity,life_value) self.script=script def attack(self,enemy): Hero.attack(enemy) print("%s attck %s" % (self.nickname,enemy)) g1=Garen("Garen",20,200,"我是盖伦") a1=Alex("Alex",10,300,"我是亚历山大") print(Hero.__bases__) print(Garen.__bases__) # (<class 'object'>,) # (<class '__main__.Hero'>,) print(g1.attack(a1.nickname)) print(g1.script) # Hero attck # Garen attck Alex # None
# 解决非关联类,是(有) 的关系,使用代码重用,用继承不能实现,要用组合,将一个类作为另一个类的输入
# 老师、学生与课程

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,course_name,course_price,course_period):
        self.course_name=course_name
        self.course_price=course_price
        self.course_period=course_period

python_obj=Course("python",20000,"7m")
t1=Teacher("alex","male",python_obj)
s1=Student("adamander","male",python_obj)
print(t1.__dict__)
print(s1.__dict__)
# {'name': 'alex', 'sex': 'male', 'course': <__main__.Course object at 0x1036014e0>}
# {'name': 'adamander', 'sex': 'male', 'course': <__main__.Course object at 0x1036014e0>}
# 非关联类老师、学生与生日
class Teacher:
    def __init__(self,name,sex,birth):
        self.name=name
        self.sex=sex
        self.birth=birth
class Student:
    def __init__(self,name,sex,birth):
        self.name=name
        self.sex=sex
        self.birth=birth

class Birth:
    def __init__(self,birth_date,birth_gift,birth_cake):
        self.birth_date=birth_date
        self.birth_gift=birth_gift
        self.birth_cake=birth_cake

birth_obj=Birth("11月11号","bmw car","banana cake")
t2=Teacher("alex","male",birth_obj)
s2=Student("adamander","male",birth_obj)
print(t2.__dict__)
print(s2.__dict__)
# {'name': 'alex', 'birth': <__main__.Birth object at 0x103601588>, 'sex': 'male'}
# {'name': 'adamander', 'birth': <__main__.Birth object at 0x103601588>, 'sex': 'male'}

类的封装

# 第一个层面的封装(什么都不用做):
# 创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装
# 注意:对于这一层面的封装(隐藏),类名.和实例名.就是访问隐藏属性的接口

# 第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),
# 只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。

# 在python中用双下划线的方式实现隐藏属性(设置成私有的),单下划线是保护变量
# 对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部使用接口函数

# 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的




# 为什么要用property
# 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,本来是obj.name(),
# 用了@property这个装饰器以后,只需要obj.name
# 用户根本无法察觉自己的name是执行了一个函数然后计算出来的,
# 这种特性的使用方式遵循了统一访问的原则,大概是类似统一访问属性这种

类的多态

# 多态和多态性:
# 多态:一种事物有多种形态,比如一个抽象类有多个子类,动物的多态:人,牛,羊,狗
# 多态性:具有不同功能的函数可以使用相同的函数名    
# 同一种行为叫:人的叫,狗的叫,猫的叫


import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass


class Peoole(Animal):
    def talk(self):
        print("people talk")

class Sheep(Animal):
    def talk(self):
        print("sheep talk")

class Cow(Animal):
    def talk(self):
        print("cow talk")


c=Cow()
s=Sheep()
p=Peoole()


# 多态性:具有不同功能的函数可以使用相同的函数名
def func(animal):
    animal.talk()
func(c)
func(s)
func(p)

# 多态的好处:
# 1.增加了程序的灵活性
# 以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
# 2.增加了程序额可扩展性
# 通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用     

 接口函数隐藏访问内部隐藏属性

# 接口函数访问内部隐藏数据属性
# class A:
#     def __init__(self):
#         self.__x=1
#     def tell(self):
#         print(self.__x)

# a=A()
# a.tell()


# 接口函数访问内部隐藏函数属性
class A:


    def __fa(self):
        print("hello word class A")
    def test(self):
        print(self.__fa())

class B(A):
     def hello(self):
         print("B")

b=B()
b.test()

经典类和新式类

经典类是py2  的深度优先的类

新式类是py3  的广度优先的类

 

posted @ 2017-09-12 20:31  Adamanter  阅读(203)  评论(0编辑  收藏  举报