初识面向对象

1.面向对象的定义:3.7新特性html

2.面向对象的组合java

3.面向对象的三大特性python

 

面向过程 VS 面向对象 

面向过程的程序设计的核心是过程(流水线式思惟),过程即解决问题的步骤,面向过程的设计就比如精心设计好一条流水线,考虑周全何时处理什么东西。

优势是:极大的下降了写程序的复杂度,只须要顺着要执行的步骤,堆叠代码便可。

缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。

应用场景:一旦完成基本不多改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

 

面向对象的程序设计的核心是对象(上帝式思惟),要理解对象为什么物,必须把本身当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也能够创造出来。面向对象的程序设计比如如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题须要四我的:唐僧,沙和尚,猪八戒,孙悟空,每一个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的属性和方法),然而这并很差玩,因而如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。而后取经开始,师徒四人与妖魔鬼怪神仙互相缠斗着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。

面向对象的程序设计的

优势是:解决了程序的扩展性。对某一个对象单独修改,会马上反映到整个体系中,如对游戏中一我的物参数的特征和技能修改都很容易。

缺点:可控性差,没法向面向过程的程序设计流水线式的能够很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即使是上帝也没法预测最终结果。因而咱们常常看到一个游戏人某一参数的修改极有可能致使阴霸的技能出现,一刀砍死3我的,这个游戏就失去平衡。

应用场景:需求常常变化的软件,通常需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。

在python 中面向对象的程序设计并非所有。

面向对象编程可使程序的维护和扩展变得更简单,而且能够大大提升程序开发效率 ,另外,基于面向对象的程序可使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

了解一些名词:类、对象、实例、实例化

类:具备相同特征的一类事物(人、狗、老虎)

对象/实例:具体的某一个事物(隔壁阿花、楼下旺财)

实例化:类——>对象的过程(这在生活中表现的不明显,咱们在后面再慢慢解释)
面向过程VS面向对象

 

面向对象的定义git


类的定义,对象的实例化,类和对象的操做面试

class Person:                                                        #类名,类名都默认大写开头
    country = 'China'#创造了一个只要是这个类就必定有的属性
                      #类属性 静态属性
    def __init__(self,*args):                                        #初始化方法,self是对象,是必须传参数
        #print(self.__dict__)
        self.name = args[0]
        self.hp = args[1]
        self.aggr = args[2]
        self.sex = args[3]
        #print(self.__dict__) 能够把self当作一个字典,self后面的参数,是它的key,  类名()这里括号里的参数,传进来后是它的value
        #print(id(self))
#注意,init的方法不能写返回值
    def walk(self,n):                                                #此处叫作方法,self必须传,且在第一个,后面还能够传其余参数
        #注意此处self是默认写法,且这个参数必须传可是若是这里写成 s或者其余名字也不要紧,由于当alex传值进来的时候,其实就能够取到值了,这里只是个形参
        #因此其实此处walk和__init__实际上是两个独立函数,也能够放在__init__上面,可是别这么写
        print('%s在散步,走了%s步'%(self.name,n))


#注意此处Person.name确定是取值不到的,类比你问你们,人类的名字是什么,可是 能够调用类属性 Person.country
alex = Person('gousheng',100,1,'不详')   #一旦开始初始化,就调用了object里的 __new__方法,建立了self
# print(alex)
print(alex.__dict__)#查看全部的属性
# print(alex.name)
# print(id(alex))  #alex和self内存地址id都是同样的,因此能够当作self就是alex
alex.walk(5) #等价于 Person.walk(alex),这是一种简写.alex做为类的对象,能够调用类的方法,并自动把自己属性传进去
#而后自己自动传进去了,因此此时只须要再传一个n给 walk方法

print(Person.__dict__['country']) #由于能够用__dict__方法,因此能够像操做字典同样调用key value,可是类的字典不能改,对象才能改
#可是这样改静态属性
Person.country = 'others'

print(alex.__dict__)               #同时能够 alex.__dict__['name'] = 'gkx' 经过这样来改属性,可是通常不这么用

print(alex.name)
alex.name = 'gkx'  #通常这么修改   本质上是调用了__dict__方法
print(alex.name)

#对象 = 类名()
#过程:
    #类名() 首先 会创造出一个对象,建立了一个self变量
    #调用init方法,类名括号里的参数会被这里接收
    #执行init方法
    #返回self,也就返回给了alex对象自己
#对象能作的事:
    #查看属性
    #调用方法
    #__dict__ 对于对象的增删改查操做,均可以经过字典的语法进行
#类名能作的事:
    #实例化
    #调用静态属性(类属性)
    #__dict__ 对于类中的dict方法,只能看不能操做
面向对象的定义
#通常来讲你的值就是属性,动做就是方法

class Person:
    def __init__(self,name,hp,aggr,sex):
        self.name = name
        self.hp = hp
        self.aggr = aggr
        self.sex = sex

    def attack(self,dog):  #把狗的实例化传进来
        dog.hp -= self.aggr
        print('%s被打了,掉了%s点血,剩下%s生命值'%(dog.name,self.aggr,dog.hp))

class Dog:
    def __init__(self,name,hp,aggr,kind):
        self.name = name
        self.hp = hp
        self.aggr = aggr
        self.kind = kind

    def bite(self, person):
        person.hp -= self.aggr
        print('%s被咬了,掉了%s点血,剩下%s生命值'%(person.name,self.aggr,person.hp))

alex = Person('alex',200,2,'不详')
jin = Dog('jinlaoban',600,50,'teddy')
alex.attack(jin)
jin.bite(alex)
# print(alex.__dict__)
练习1-人狗大战
 #使用面向对象的状况
#当有几个函数,须要反反复复传入相同参数的时候,就能够考虑面向对象,这些参数都是对象的属性
#很是明显的处理一类事物 这些事物都有类似的属性和功能
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def kanchai(self):
        print('%s,%s,%s,上山去砍柴'%(self.name,self.age,self.sex))

    def kaiche(self):
        print('%s,%s,%s,开车去东北'%(self.name,self.age,self.sex))

    def baojian(self):
        print('%s,%s,%s,去大保健'%(self.name,self.age,self.sex))

ming = Person('小明','10岁','')
wang = Person('老王','90岁','')
ming.kanchai()
wang.kaiche()


# import sys
# print(sys.path)
from math import pi
class Circle:

    def __init__(self,radi):
        self.radi = radi

    def permi(self):
        return pi*self.radi*2
        # print(2*pi*self.radi)

    def area(self):
        return pi*self.radi**2
        # print(pi*self.radi**2)

yuan = Circle(4)
print(yuan.permi())
print(yuan.area())
练习2-定义circle类,使用方法
class Foo:
    def func(self):    #当类中没有 __init__ 也能够实例化,可是就没有办法给实例传属性了
                        #不能初始化self,此处的self只是一个普通参数,接收的是一个 空的实例
        print('no init')

f1 = Foo()
f1.func()
能够没有__init__吗
#类能够定义两种属性  静态属性(类属性) 和 动态属性(方法)
#类能够约束属性

class Course:
    language = 'Chinese'
    def __init__(self,teacher,course_name,period,price):
        self.teacher = teacher
        self.name = course_name
        self.period = period
        self.price = price

print(Course.language)
python = Course('egon','python','6months',20000)
print(python.__dict__)



#对象中有指向类的指针,当对象寻找language的时候,先在自身的内存地址找,没找到,再去类里面找
#可是类不能找对象的,Course.name调用不到的
#类中的静态变量,能够被对象和类调用

#咱们知道
Course.language = 'English' #这样子是能够修改的
#可是
python.language = 'English' #也是能够运行成功的,可是此时,对象是无权更改 Course里的不可变数据类型的
#而后又在本身内部找不到 language去修改,因此 python这个对象在本身内部建立了 一个 language
print(python.__dict__) #此时里面多了个language
#此时python这个对象,就再也接收不到 类里的静态属性了,除非:
del python.language #删除掉其内部的language才能够从新接收

#因此:对于不可变数据类型来讲(str,int),最好是用 类 去调用,尽可能不要从 对象 调用

              #~~~~~~~可变和不可变的静态属性的区别~~~~~~~~~
#可是对于 可变数据类型   好比 language = ['Chinese']   python.language[0]='English'是能够改变 类 中对应的值的
#由于 对于列表来讲,其内存地址确定不变,里面是什么元素都无所谓
#对于 可变数据类型 对象的修改是共享,从新赋值是独立的


#小练习
class Foo:
    count = 0
    def __init__(self):
        Foo.count += 1

f1 = Foo()
print(Foo.count)
f2 = Foo()
print(Foo.count)
面向对象的命名空间
静态属性补充:
        因为 self就能够当作是类的对象自己。对于类到的静态属性,在类外能够用 对象.static_name 来访问。天然在类中也能够 用 self.静态名 来访问了!
        >>> class A:
            x = 12
            def px(self):
                print("A中的x",self.x)
        
                
        >>> a = A()
        >>> a.px()
        A中的x 12
        >>> 
类中静态属性也能够用self调用

#面向对象的命名空间:类和对象,分别调用什么属性。编程

#注意类的定义,若是__init__里的参数都给了默认值,那么在实例化的时候,能够不带参数。相似函数的形参方法及传参顺序设计模式

 

面向对象的组合微信


# 组合 :一个对象的属性值是另一个类的对象
#        alex.weapon 是 Weapon类的对象
import time
class Person:
    def __init__(self,name,hp,aggr,sex):
        self.name = name
        self.hp = hp
        self.aggr = aggr
        self.sex = sex
        self.money = 0

    def attack(self,dog):  #把狗的实例化传进来
        dog.hp -= self.aggr
        print('%s被打了,掉了%s点血,剩下%s生命值'%(dog.name,self.aggr,dog.hp))

    def get_weapon(self,weapon):
        if self.money > weapon.price:
            self.money -= weapon.price
            self.weapon = weapon
            self.aggr += weapon.aggr


class Dog:
    def __init__(self,name,hp,aggr,kind):
        self.name = name
        self.hp = hp
        self.aggr = aggr
        self.kind = kind

    def bite(self, person):
        person.hp -= self.aggr
        print('%s被咬了,掉了%s点血,剩下%s生命值'%(person.name,self.aggr,person.hp))

class Weapon:
    def __init__(self,name,aggr,njd,price):
        self.name = name
        self.aggr = aggr
        self.njd = njd
        self.price =price

    def beatdragon(self,person):
        if self.njd > 0:
            person.hp -= self.aggr*2
            print('%s被打了,掉了%s点血,剩下%s生命值' % (person.name, self.aggr*2, person.hp))
            self.njd -=1

alex = Person('alex',100,0.5,'不详')
jin = Person('jinlaoban',500,100,'teddy')
w = Weapon('打狗棒',100,3,998)

alex.money += 1000
alex.attack(jin)
time.sleep(0.5)
alex.get_weapon(w)
time.sleep(0.5)
alex.attack(jin)
time.sleep(0.5)
alex.weapon.beatdragon(jin)
面向对象的组合
#组合
#1 能够在初始化中 令   self.name = Lei(name,args1,args2..) 括号里的值直接是具体的值
#2 能够在初始化中 令   self.name = name  而后后续中  把一个其余类的对象  传入 name 中
#3 能够在方法中,令  self.new = new  这个new为方法中传入的对象
#4 能够在运行过程当中 令  self.xxx = 对象
#只要一发生,一个对象的属性值是另外一个对象,则就是组合
#练习1
from cmath import pi
class Circle:
    def __init__(self,r):
        self.r = r

    def area(self):
        return pi*self.r**2

    def peri(self):
        return pi*self.r*2
# a = Circle(3)
# print(a.area())
# print(a.peri())

class Ring:
    def __init__(self,inside_r,outside_r):
        self.inside_r = Circle(inside_r)
        self.outside_r = Circle(outside_r)

    def area(self):
        return self.outside_r.area()-self.inside_r.area()

    def peri(self):
        return self.inside_r.peri()+self.outside_r.peri()

b = Ring(10,20)
print(b.area())
print(b.peri())

#练习2
class Course:
    def __init__(self,course_name,period,price):
        self.name = course_name
        self.period = period
        self.price = price

class Teacher:
    def __init__(self,name,course,sex,birh):
        self.name = name
        self.course = course
        self.sex = sex
        self.birh = birh
        self.course = Course('python', '6 month', 2000)


class Birth:
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

bb = Birth(1981,9,22)
jing = Teacher('jing','python','femal',bb)
print(jing.birh.year)
组合练习

#什么是组合,何时使用组合网络

#一个类是能够没有 init 方法的,可是一旦没有,就没办法初始化self
class Foo:
    def func(self):    #当类中没有 __init__ 也能够实例化,可是就没有办法给实例传属性了
                        #不能初始化self,此处的self只是一个普通参数,接收的是一个 空的实例
        print('no init')

f1 = Foo()
f1.func()

print(f1.func)
#<bound method Foo.func of <__main__.Foo object at 0x0000022110C02780>>
#到目前为止,只有对象调用类的方法,才称为绑定方法  对象和类方法发生绑定关系


# 包 —— __init__
# import package —— 类的实例化的过程
# import time
# time.time()
绑定方法

 

面向对象的三大特性app

一.继承

#python3中的类 叫作  新式类
#继承是一种建立新类的方式,在python中,新建的类能够继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
#父类又称 基类,超类    子类又称 派生类
#一个父类能够被屡次继承,  在python中一个子类能够继承多个父类
#只有子类能找到父类,父类不知道本身有什么子类

class A:pass
class B:pass
class A_son(A):pass
class B_son(A,B):pass
print(A_son.__bases__) #(<class '__main__.A'>,)
print(A.__bases__)  #(<class 'object'>,)   这个 object 是全部类的祖宗,没有继承父类的类,能够看做其父类是 object
#在python3中全部的类都有父类,python3中的类又名 新式类
#也就说是说 class A:pass  写成  class A(object):pass 也是彻底没问题的。

#小例子
# class Animal:
#     def __init__(self,name,aggr,hp):
#         self.name = name
#         self.aggr = aggr
#         self.hp = hp
# class Dog(Animal):
#     pass
# class Person(Animal):
#     pass
#
# jin = Dog('金老板',200,500)
# print(jin.name)

# 狗类 吃 喝 看门(guard)
# 鸟类 吃 喝 下蛋(lay)
class Animal:
    def __init__(self):
        print('执行Animal.__init__')
        self.func()
    def eat(self):
        print('%s eating'%self.name)
    def drink(self):
        print('%s drinking'%self.name)
    def func(self):
        print('Animal.func')

class Dog(Animal):    #当本身没有init方法的时候,使用父类的 init
                      #此时Dog类建立了一个self,可是没初始化值,因此回父类,init,而后接着 调用 self.func(),此时调用的是 Dog.fun(self)
                      #当本身有就调用本身的,没有才会去找父类
    def guard(self):
        print('guarding')
    def func(self):
        print('Dog.func')
dog = Dog()

# class Bird(Animal):
#     def __init__(self,name):
#         self.name = name
#     def lay(self):
#         print('laying')
#
# b = Bird('jin')
# print(b.name)
初识继承
#关于组合和继承
#组合是 有,好比 老师类里有生日类
#继承是 是,子类是父类的关系,好比 dog是动物
#判断是 有 仍是 是,来使用组合仍是继承,还能够判断是否有重复代码,有则是继承

class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp

    def eat(self):
        print('吃药回血')
        self.hp+=100

class Dog(Animal):
    def __init__(self,name,hp,aggr,kind):
        Animal.__init__(self.name,aggr,hp)  #此处的self,传的是 Dog类的self,这样就能够用Animal来把name,aggr,hp,初识给Dog类的self
        self.kind = kind              #此时即为派生属性

    def eat(self):
        Animal.eat(self)         #若子类方法和父类方法同名,既想实现父类的方法也想实现子类的方法,则须要在此调用父类的方法,传入的self是 子类自己的
        self.teeth = 2
    def bite(self, person):         #派生方法
        person.hp -= self.aggr
        print('%s被咬了,掉了%s点血,剩下%s生命值'%(person.name,self.aggr,person.hp))



class Person(Animal):
    def __init__(self,name,hp,aggr,sex):
        Animal.__init__(self.name, aggr, hp)
        self.name = name
        self.hp = hp
        self.aggr = aggr
        self.sex = sex

    def attack(self,dog):  #把狗的实例化传进来
        dog.hp -= self.aggr
        print('%s被打了,掉了%s点血,剩下%s生命值'%(dog.name,self.aggr,dog.hp))

# 父类中没有的属性 在子类中出现 叫作派生属性
# 父类中没有的方法 在子类中出现 叫作派生方法
# 只要是子类的对象调用,子类中有的名字 必定用子类的,子类中没有才找父类的,若是父类也没有报错
# 若是父类 子类都有 用子类的
#可是若是非要用父类的方法,而本身子类已经用同名方法,则须要在子类的方法中调用 Animal.eat(self) 此处的self传的是子类的self
初识继承-派生
#super 是python3中才有的方法
class Animal:
    def __init__(self,name,aggr,hp):
        self.name = name
        self.aggr = aggr
        self.hp = hp
    def eat(self):
        print('在animal中,回血了')

class Dog(Animal):
    def __init__(self,name,aggr,hp,kind):
        #Animal.__init__(self,name,aggr,hp) #注意此处参数顺序,对于直接用父类进行init,参数顺序和子类同样便可
            # 对于用super进行init,子类参数顺序必定要和父类同样,会以父类的参数顺序进行实例化,由于是父类在帮忙实例化Dog的self
        super().__init__(name,aggr,hp)  #super(Dog, self).__init__(name,aggr,hp) 括号中的 Dog类和self能够省略
        self.kind = kind         #派生属性顺序只要按子类传入顺序便可

    def eat(self):
        #Animal.eat(self)   #若是子类中有同名的方法,子类会优先调用本身的方法,若是本身没有,才返回去找父类要
        super().eat()       #两种方式调取父类中的方法
        print('在Dog类中')

jin = Dog('金老板',100,500,'teddy')
print(jin.__dict__)
jin.eat()  #此处若是
super(Dog,jin).eat()   #super在类外面调用,就要传 dog类和对应的对象
super方法
#有道词典0909笔记
# 新式类有个原则,就是全部点都要找到,若是保证这个点能找到,广度优先(钻石问题,小乌龟问题)
# python3中全部的类都是 新式类,都采用广度优先,有个方法能够查看继承顺序  print(B.mro())
# 在python2中的经典类,则时深度优先,一条路走到黑,走过的路不会走,而后换另外一条路
# python2中的新式类和经典类,能够看下面的文章
# https://www.cnblogs.com/summer-cool/p/3884526.html
#平常工做中主要仍是使用单继承,多继承多用在设计模式中,及面试
# class F:
#     def func(self): print('F')
# class A(F):pass
#     # def func(self): print('A')
# class B(A):
#     pass
#     # def func(self): print('B')
# class E(F):pass
#     # def func(self): print('E')
# class C(E):
#     pass
#     # def func(self): print('C')
#
# class D(B,C):
#     pass
#     # def func(self):print('D')
#
# d = D()
# # d.func()
# print(D.mro())

# 新式类中的继承顺序 : 广度优先


class A(object):   #著名的钻石问题
    def func(self): print('A')

class B(A):
    def func(self):
        super().func()
        print('B')

class C(A):
    def func(self):
        super().func()
        print('C')

class D(B,C):
    def func(self):
        super().func()
        print('D')

b = D()
b.func()    #>>>  打印结果为  A  C   B   D
print(B.mro())
#2.7
# 新式类 继承object类的才是新式类 广度优先
# 经典类 若是你直接建立一个类在2.7中就是经典类 深度优先
# print(D.mro())
# D.mro()

# 单继承 : 子类有的用子类 子类没有用父类
# 多继承中,咱们子类的对象调用一个方法,默认是就近原则,找的顺序是什么?
# 经典类中 深度优先
# 新式类中 广度优先
# python2.7 新式类和经典类共存,新式类要继承object
# python3   只有新式类,默认继承object
# 经典类和新式类还有一个区别  mro方法只在新式类中存在
# super 只在python3中存在
# super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的

# 继续写做业 :
# 学生管理系统  登陆,识别身份   进阶 : 不一样视图不一样的菜单
多继承

#多继承主要涉及到继承顺序,在新式类中是广度优先,经典类中是深度优先,有个查看继承顺序的方法  claaaname.mro()

继承特性中的两大设计模式:接口类和抽象类。褒贬不一,重视程度不一

#接口类和抽象类都不能实例化
# java : 面向对象编程
# 设计模式   —— 接口
# 接口类 : python原生不支持,知足接口隔离原则
            #接口类支持多继承
            #我要实现不一样的功能,我就要去实现不一样的接口,来继承这些功能。同时我要规范不一样的接口要有哪些方法。
            #规范的时候不实现这些方法,只在子类里实现

# 抽象类 : python原生支持的

from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):  # 元类 默认的元类 type
    @abstractmethod             #检测子类的代码是否有相同的方法
    def pay(self,money):pass   # 没有实现这个方法

    @abstractmethod
    def func2(self):pass       #能够在这个规范中定义不少方法,这些方法只提供方法名,可是彻底不用去实现。
                                #而后以这个方法做为父类,当咱们写类方法的时候,若是遗漏了某个方法,或拼写错误,就会及时报错
# 规范 :接口类或者抽象类均可以
# 接口类 支持多继承,接口类中的全部的方法都必须不能实现 —— java
# 抽象类 不支持多继承,抽象类中方法能够有一些代码的实现 —— java
class Wechat(Payment):
    def pay(self,money):
        print('已经用微信支付了%s元'%money)

class Alipay(Payment):
    def pay(self,money):
        print('已经用支付宝支付了%s元' % money)

class Applepay(Payment):
    def pay(self,money):  #当若是这里的方法不叫pay,叫作fuqian,那么最上面的规范,就会报错,告诉你没调用到pay方法
        print('已经用applepay支付了%s元' % money)

def pay(pay_obj,money):  # 统一支付入口
    pay_obj.pay(money)

# wechat = Wechat()
# ali = Alipay()
app = Applepay()
# wechat.pay(100)
# ali.pay(200)
p = Payment()
接口类
#规范
#这个例子是典形的 接口类 作的事情

#接口类
#我要实现不一样的功能,我就要去实现不一样的接口,来继承这些功能。同时我要规范不一样的接口要有哪些方法。
#规范的时候不实现这些方法,只在子类里实现

# tiger 走路 游泳
# swan 走路 游泳 飞
# oldying 走路 飞
from abc import abstractmethod,ABCMeta
class Swim_Animal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):pass

class Walk_Animal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):pass

class Fly_Animal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):pass

class Tiger(Walk_Animal,Swim_Animal):
    def walk(self):
        pass
    def swim(self):
        pass
class OldYing(Fly_Animal,Walk_Animal):pass
class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass

# 接口类  恰好知足接口隔离原则 面向对象开发的思想 规范
接口类的多继承
#接口类 : python原生不支持,知足接口隔离原则
# 接口类 支持多继承,接口类中的全部的方法都必须不能实现 —— java


# 抽象类 : python原生支持的
# 抽象类 不支持多继承,抽象类中方法能够有一些代码的实现 —— java
#抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
#若是说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

#在接口类中,经过规范不一样的接口,最后各个子类,去继承这些接口类(多继承),来达到实现功能的目的,接口类的规范,使得子类不会遗漏功能和拼写错误
#在抽象类中,经过规范抽象出来的父类,当子类继承的时候(单继承),必须包含抽象类(父类)的功能,从而规范了子类
#抽象类中,子类方法必定要包含父类方法,只能多不能少

#一切皆文件
import abc #利用abc模块实现抽象类

class All_file(metaclass=abc.ABCMeta):
    all_type='file'
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def read(self):
        '子类必须定义读功能'
        with open('filaname') as f:
            pass

    @abc.abstractmethod #定义抽象方法,无需实现功能
    def write(self):
        '子类必须定义写功能'
        pass

class Txt(All_file): #子类继承抽象类,可是必须定义read和write方法
    def read(self):
        print('文本数据的读取方法')
    def write(self):
        print('文本数据的读取方法')

class Sata(All_file): #子类继承抽象类,可是必须定义read和write方法
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

class Process(All_file): #子类继承抽象类,可是必须定义read和write方法
    def read(self):
        print('进程数据的读取方法')

    def write(self):
        print('进程数据的读取方法')

wenbenwenjian=Txt()

yingpanwenjian=Sata()

jinchengwenjian=Process()

#这样你们都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()

print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)

#为何接口类中不能实现简单功能
# 抽象类 : 规范
# 通常状况下 单继承 能实现的功能都是同样的,因此在父类中能够有一些简单的基础实现
# 多继承的状况 因为功能比较复杂,因此不容易抽象出相同的功能的具体实现写在父类中


# 抽象类仍是接口类 : 面向对象的开发规范 全部的接口类和抽象类都不能实例化
# java :
# java里的全部类的继承都是单继承,因此抽象类完美的解决了单继承需求中的规范问题
# 但对于多继承的需求,因为java自己语法的不支持,因此建立了接口Interface这个概念来解决多继承的规范问题

# python
# python中没有接口类  :
  #  python中自带多继承 因此咱们直接用class来实现了接口类
# python中支持抽象类  : 通常状况下 单继承  不能实例化
  #  且能够实现python代码
抽象类的单继承
# java : 面向对象编程
# 设计模式   —— 接口
# 接口类 : python原生不支持,知足接口隔离原则,不能被实例化,接口类中的全部的方法都必须不能实现(java)
            #接口类支持多继承
            #我要实现不一样的功能,我就要去实现不一样的接口,来继承这些功能。同时我要规范不一样的接口要有哪些方法。
            #规范的时候不实现这些方法,只在子类里实现


# 抽象类 : python原生支持的
# 抽象类 不支持多继承(或者说通常都是单继承),抽象类中方法能够有一些代码的实现 —— java
#抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
#若是说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。


         #功能归纳
#在接口类中,经过规范不一样的接口,最后各个子类,去继承这些接口类(多继承),来达到实现功能的目的,接口类的规范,使得子类不会遗漏功能和拼写错误
#在抽象类中,经过规范抽象出来的父类,当子类继承的时候(单继承),必须包含抽象类(父类)的功能,从而规范了子类
#抽象类中,子类方法必定要包含父类方法,只能多不能少
#接口类和抽象类都不能实例化
#接口类和抽象类,这两种最主要的仍是规范了固定的功能,就是这些规范了的方法必定要实现。且具体的功能和子类本身自己的功能仍是要在子类中实现
#面试两句话:这两种都是规范,python中没有接口类


            #为何接口类中不能实现简单功能
# 抽象类 : 规范
# 通常状况下 单继承 能实现的功能都是同样的,因此在父类中能够有一些简单的基础实现
# 多继承的状况 因为功能比较复杂,因此不容易抽象出相同的功能的具体实现写在父类中


# 多态 python 天生支持多态
# 接口类和抽象类 在python当中的应用点并非很是必要,不崇尚这两类设计模式
#ptyhon中崇尚的是鸭子类型(模仿,一个跟一个),好比list和tuple,有好几个类似方法,也没有采用继承来获得


#在其余静态语言类型中java等,要给函数传值,必需要先定义数据类型,因此在归一化设计的时候,类做为变量传入的时候,须要提供一个父类,做为数据类型定义,再传入
#此时这个父类,空着也是空着,干脆作一些规范(接口类和抽象类),一箭双雕



# java :
# java里的全部类的继承都是单继承,因此抽象类完美的解决了单继承需求中的规范问题
# 但对于多继承的需求,因为java自己语法的不支持,因此建立了接口Interface这个概念来解决多继承的规范问题

# python:
# python中没有接口类  :
  #  python中自带多继承 因此咱们直接用class来实现了接口类
# python中支持抽象类  : 通常状况下 单继承  不能实例化
  #  且能够实现python代码

#python中抽象类和接口类自己很类似,由于这种设计模式,是从java中学习过来的,有些公司推崇,有些没有推崇
#python自己就支持多继承,因此没有接口类。
#因此受java影响,通常接口类用于多继承,抽象类用于单继承
抽象类和接口类总结

 

二.多态


python天生支持多态

# 多态 python 天生支持多态
# 接口类和抽象类 在python当中的应用点并非很是必要,不崇尚这两类设计模式
#ptyhon中崇尚的是鸭子类型(模仿,一个跟一个),好比list和tuple,有好几个类似方法,也没有采用继承来获得


#在其余静态语言类型中java等,要给函数传值,必需要先定义数据类型,因此在归一化设计的时候,类做为变量传入的时候,须要提供一个父类,做为数据类型定义,再传入
#此时这个父类,空着也是空着,干脆作一些规范(接口类和抽象类),一箭双雕


# def func(int num,str name):
#     pass
#
# func('alex',2)
# class Payment:pass

# class Alipay():
#     def pay(self,money):
#         print('已经用支付宝支付了%s元' % money)
#
# class Applepay():
#     def pay(self,money):
#         print('已经用applepay支付了%s元' % money)
#
# def pay(pay_obj,money):  # 统一支付入口  归一化设计
#     pay_obj.pay(money)
#
# pay()

# 什么是多态
# python 动态强类型的语言
# 鸭子类型
# list tuple
# 不崇尚根据继承所得来的类似
# 我只是本身实现我本身的代码就能够了。
# 若是两个类恰好类似,并不产生父类的子类的兄弟关系,而是鸭子类型
# list tuple 这种类似,是本身写代码的时候约束的,而不是经过父类约束的
# 优势 : 松耦合 每一个类似的类之间都没有影响
# 缺点 : 太随意了,只能靠自觉

class List():
    def __len__(self):pass
class Tuple():
    def __len__(self):pass

def len(obj):
    return obj.__len__()

l = Tuple()
len(l)

# 强类型语言     多态
# python 语言    鸭子类型


# 接口类和抽象类 在python当中的应用点并非很是必要
多态和鸭子类型

 

三.封装


重要知识点

#重要知识点
# 广义上面向对象的封装 :代码的保护,面向对象的思想自己就是一种
# 只让本身的对象能调用本身类中的方法

# 狭义上的封装 —— 面向对象的三大特性之一
# 属性 和 方法都藏起来 不让你看见
class Person:
    __key = 123  # 私有静态属性
    def __init__(self,name,passwd):
        self.name = name
        self.__passwd = passwd   # 私有属性

    def __get_pwd(self):         # 私有方法
        return self.__passwd   #只要在类的内部使用私有属性,就会自动的带上_类名

    def login(self):          # 正常的方法调用私有的方法
        return self.__get_pwd()

alex = Person('alex','alex3714')
print(alex.__dict__)    #设置私有变量,其实都是在变量名的基础上加  _Person
print(Person.__dict__)
print(alex._Person__get_pwd())
# print(alex._Person__passwd)   # _类名__属性名
# print(alex.login())

# 全部的私有 都是在变量的左边加上双下划綫
    # 对象的私有属性
    # 类中的私有方法
    # 类中的静态私有属性
# 全部的私有的 都不能在类的外部使用
初识封装
#在C++语言中为了保密,将全部的类属性都设置为私有
#父类中的私有属性,不能被子类调用

#总结
#会用到私有属性的场景
#1.隐藏起一个属性,不想让类的外部调用
#2.保护一个属性,不想让属性随意被改动
#3.保护一个属性,不想让子类调用
封装总结
# 装饰器:  @property     @func.setter(能够传惟一一个参数)   #func.deleter(与del配合使用)
# from math import pi
# print(pi)
#
# class Circle:
#     def __init__(self,r):
#         self.r = r        #为何不把面积写在属性里 self.area = pi*self.r**2。由于代码属性规范,面积不能直接改,只能用半径改。
#
#     @property
#     def perimeter(self):
#         return pi*self.r*2
#
#     @property
#     def area(self):
#         return pi*self.r**2
#
# c = Circle(5)
# print(c.area)
# print(c.perimeter )

class Goods:
    discount = 0.5
    def __init__(self,name,price):
        self.__name = name
        self.price = price               #想调用私有属性
    @property                           #加了property后可让在类外调用函数,像调用属性同样,即免去加括号。可是此处就不能传参了
    def name(self):
        return self.__name+'没过时'
    @name.setter                       #在有 @property装饰的name后,若是想修改私有属性,能够继续调用装饰器  函数名.setter
    def name(self,new_name):           #而后定义一个如出一辙的函数,参数为传入想改的值。
        self.__name = new_name

    @property
    def get_price(self):
        return self.price * Goods.discount


# apple = Goods('apple',5)
# print(apple.name)
# apple.name = '香蕉'
# print(apple.name)
# print(apple.get_price)

class Person:
    def __init__(self,name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.deleter       #这个deleter只有和调用的时候  del p.name 相做用才会实现函数功能
    def name(self):
        del self.__name
p = Person('erge')
print(p.name)
del p.name         #这个del啥都没作,只是执行了name方法,且deleter只有和调用的时候  del p.name 相做用才会实现函数功能
print(p.name)      #我不能用对象去删除一个方法,没权力
封装的应用-@property,.setter,.deleter
# staticmathod  静态的方法 ***
# classmethod   类方法    ****
# 类的操做行为
# class Goods:
#     __discount = 0.8
#     def __init__(self,name,price):
#         self.name = name
#         self.__price = price
#     @property
#     def price(self):
#         return self.__price * Goods.__discount
#     @classmethod   # 把一个方法 变成一个类中的方法,这个方法就直接能够被类调用,不须要依托任何对象
#     def change_discount(cls,new_discount):  # 修改折扣
#         cls.__discount = new_discount
# apple = Goods('苹果',5)
# print(apple.price)
# Goods.change_discount(0.5)   # Goods.change_discount(Goods)
# print(apple.price)
# 当这个方法的操做只涉及【静态属性】的时候 就应该使用classmethod来装饰这个方法

# java
class Login:
    def __init__(self,name,password):
        self.name = name
        self.pwd = password
    def login(self):pass

    @staticmethod
    def get_usr_pwd():   # # 静态方法 没有默认的参数 就象函数同样 ,固然也能够传参数
        usr = input('用户名 :')
        pwd = input('密码 :')
        Login(usr,pwd)

# Login.get_usr_pwd()
getattr(Login,'get_usr_pwd')()
# 在彻底面向对象的程序中,
# 若是一个函数 既和类没有关系,也和对象没有关系,就用staticmethod将它变为一个静态方法,随时都能调用



# 类方法和静态方法 都是类调用的
# 对象能够调用类方法和静态方法么?   能够   通常状况下 推荐用类名调用
# 类方法 有一个默认参数 cls 表明这个类  cls
# 静态方法 没有默认的参数 就象函数同样


# 面向对象的进阶
# 网络编程
classmethod和staticmethod

day59 Django 封装mypage这个功能,从app01中的views的函数,封装为mypage做为一个库来使用 

 

补充:

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def walk(self):
        print("%s正在散步"%self.name)
        return self #须要返回self

    def eating(self):
        print("%s正在吃饭"%self.name)


f1 = Foo("gkx",22)
f1.walk().eating()  #在walk方法中return self,而后就能够进行链式操做了
# f1.eating()
类的链式操做
class Foo:
    def func(self):    #当类中没有 __init__ 也能够实例化,可是就没有办法给实例传属性了
                        #不能初始化self,此处的self只是一个普通参数,接收的是一个 空的实例
        print('no init')

f1 = Foo()
f1.func()

#不把参数传入self
class Person:
    def __init__(self,name,age):
        self.name = name     #self就是对象。能够把self当作一个字典,self后面的参数,是它的key,  类名()这里括号里的参数,传进来后是它的value
        age = age+1          #类的实例化默认是执行__init__函数,若是__init__的参数,不传入self,那么只能在__init__中使用,类中的方法调用不到
        print(age)           #换句话说,若是一个参数在__init__使用完后就没用了,就能够不用把它传入 self

    def name_(self):
        print("你叫什么",self.name)

p = Person("gkx",22)

#self.page_start = page_start  # 当page_start判断完毕后,才传入self。对于那些直接在__init__一开始就传入self的来讲,实例化的属性就是传入的值,不存在须要判断的,因此能够直接传入
#self.page_end = page_end  # 可是此时page_start和page_end须要传入参数后,再作必定的判断才能肯定下来,肯定后才能传给self,方便方法中调用
self理解!!必定要看
#同时传入self的参数也不必定是要经过实例化传入的,也能够是通过实例化传入的参数,经过实例化传入的参数根据条件进行演变 而来的

 

 

 py3.7新特性

相关文章
相关标签/搜索