python08 OOP

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 26 20:16:58 2019

@author: cheng
"""

#1.OOP思想
 - 接触到任意一个任务,首先想到的是这个任务的构成
 -几个名词
  -oo:面向对象
  -ooa:面向对象的分析
  -OOD:面向对象的设计
  -OOI:XXX的实现
  -OOP:xxx的编程
  --OOA -> OOD ->OOI:面向对象的实现过程
  
#2.类和对象的概念
 -类:抽象名词,代表一个集合,共性的事物
 -对象:具象的事物,单个个体
 -类和对象的关系
   -一个代表一类事物的某一个
   -一个代表一大类事物
 -类中的内容,应该具有两个内容
   - 表明事物的特征,叫做属性
   - 表明事物功能,成为成员方法(函数)
   
#3.类的基本实现
 -类的命名
   - 遵循变量命名的规范
   - 大驼峰
   -尽量避开系统相似的命名
 -声明一个类
   -必须用class关键字
   -类由属性和方法构成
   -成员属性定义可以直接使用变量赋值
 -实例化类
    变量 = 类名()
 -访问对象成员
   -使用点操作符
    obj.成员属性名称
    obj.成员方法
   

#4. anaconda基本使用
 -anaconda主要是一个虚拟环境管理器
 -conda list:显示里面的安装的包
 -conda env list:显示它的虚拟环境列表
 -conda create -n xxx python=3.6:创建python版本是3.6的虚拟环境
 
#4.类和对象的成员分析
  -类和对象都可以存储成员,成员归为类所有,也可以归对象所有
  -类存储成员使用的是与类关联的一个对象
  -独享存储成员是存储在当前对象中
  -对象访问一个城市时,如果对象中没有该成员,尝试访问类中的同名成员
     如果对象中有此成员,一定使用对象中的成员
  -创建对象的时候,类中的成员不会放入对象当中,得到一个空对象,没有成员
  -通过对象对类中成员重新赋值或者通过对象添加成员时,对象成员会保存在对象中,而不会修改类成员

#5.关于self
  -self在对象的方法中表示当前对象本身,通过通过对象调用一个方法,
      那么该对象会自动传入到第一个参数中
  -self并不是关键字,只是一个普通参数,理论上可以用任何一个普通变量
  -方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,
     没有self的绑定类的方法,只能通过类访问
  -使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过__class__成员名来访问   

#6.面向对象的三大特性
  -封装
   就是对对象的成员进行访问限制
   -三个级别
    -公开、受保护的、私有的
   -判断对象的位置
    -对象内部
    -对象外部
    -子类中
   -私有
     -私有成员时最高级别的封装,只能在当前类或者对象中访问
     -在成员前面添加两个两个下划线
     class Person():
         name = 'cheng' #公有
        __age = 18     #私有
      -Python的私有不是真私有,是一种称为name magnling的改名策略
        可以使用对象._classname_attributename访问
   -受保护的封装
     -受保护的封装是将对象成员进行一定级别的封装,然后在类中或者子类中都可以进行访问,但是在外部不可以
     -封装方法:在成员名称前添加一个下划线
   -公开的
     -公共的封装实际对成员没有任何操作
  -继承
   一个类可以使用另外一个类的成员属性和成员方法
    作用:减少代码
    被继承的类叫父类,用于继承的类叫子类
    特征:
      -所有的类都继承object类
      -子类一旦继承父类,即可以使用父类的除私有成员外的所有内容
      -子类继承父类并没有将父类的成员赋值到子类中,二十通过引用关系访问调用
      -子类可以定义独有的成员属性和方法
      -子类中定义的成员和父类的一样,则优先使用子类成员
      -子类如果想扩充父类的方法,可以定义新方法的同事访问父类成员进行代码重用
    变量函数的查找顺序
      -优先查找自己的变量
      -没有则查找父类
      -构造函数如果本类中没有定义,则自动查找父类
      -如果本类有定义,则不在继续往上查找
    构造函数
      -是一类特殊的函数,在类进行实例化之前进行调用
      -如果定义了构造函数,则实例化时使用构造函数,不查找父类
      -如果没有定义,则自动查找父类
      -如果子类没有定义,父类的构造函数带参数,则构造对象时的参数应该按照父类进行
      -如果子类没有写构造函数,则自动向上查找,直到找到为止
    super
      -super不是关键字,而是一个类
      -它的作用是获取MRO列表中的第一个类
      -和父类直接没有任何实质性关系,但通过super可以调用到父类
      -使用方法,参见在构造函数中调用父类的构造函数
    单继承和多继承
      -单继承:每个类只能继承一个类
      -多继承,每个类允许继承多个类
      -优缺点:
        单继承传承有序逻辑清晰、语法简单
             功能不允许无限扩展
        多继承类的功能扩展方便
             继承关系混乱 
     菱形继承/钻石继承
       多个子类继承同一个父类
       关于多继承的MRO
         MRO是多继承中用于保存继承顺序的一个列表
         python本身采用C3算法来多继承的菱形继承进行计算的结果
         MRO的设计原则:
            子类永远在父类前面
            如果多个父类,按照括号里面的顺序执行
            如果多个类继承同一个父类,孙子类中只会选取继承语法中括号中的第一个父类的父类
    
  -多态
    同一个对象在不同情况下有不同的状态出现
    多态是一种设计思想
    一种调用方式,不同的执行效果
    同一事物的多种形态
   Mixin模式
    -主要是采用多继承方式对类的功能的进行扩展
    使用时非常小心
     -首先它表示某一个单一功能,而不是某个物品
     -职责必须单一,由多个功能,这些多个Mixin
     -Mixin不能依赖子类的实现
     -子类及时没有继承这个Mixin类,也能照样工作
    优缺点
     可以在不对类进行任何修改的情况下,扩充功能
     可以方便的组织和维护不停功能组件的划分
     可以根据需要任意调整功能类的组合
     可以避免创建很多新的类,导致类的继承混乱
#7.类的函数
   issubclass:什么是什么的子类
   isinstance:什么是什么对象实例     
   hasattr: 检测一个对象是否有成员XXX
   dir:获取对象的成员列表
   
####类的成员描述符
   类的成员描述是为了在类中对类的成员属性进行相关操作而创建的一种方式
    -get:获取
    -set:修改
    -delete:删除
   如果想使用类的成员描述符,三种方法:
    -使用类实现描述符
    -使用属性修饰符
    -使用property函数
      -property(fget,fset,fdelete,doc)
   无论哪种修饰符都是为了对成员属性进行相应的控制
    -类的方式:适合多个类中的多个属性公用一个描述符
    -property:使用当前类中使用,可以控制一个类中多个属性
    -属性修饰符:使用与当前类中使用,控制一个类中的一个属性
 ####类的内置属性
   __dict__:以字典的方式显示类的成员组成
   __doc__:获取类的文档信息
   __name__:获取类的名称,如果在模块中使用,则获取模块的名称

####类的常用魔术方法
  魔术方法就是不需要人为调用的方法,基本是在特定的时刻自动触发
  统一的特征:方法名被前后各两个下划线包裹
  操作类: 
   __init__:构造函数
   __new__: 对象实例化方法,一般不需要使用
   __call__:对象当函数使用的时候
   __str__: 当对象被当做字符串的时候调用
   __repr__:返回字符串 
  描述符相关:
   __set__:
   __get__:
   __delete__:
  属性相关:
   __getattr__:访问一个不存在的属性
   __setattr__:对成员属性进行设置的时候触发
    -参数:self用来获取当前对象
          被设置的属性名称,以字符创形式出现
          需要对属性名称设置的值
    -作用:进行属性设置的时候进行验证或者修改
    -注意:在该方法中不能对属性直接进行赋值操作,否则死循环
  运算分类相关魔术方法:
   __gt__:进行大于判断的时候触发
    参数:self 
         第二个参数是第二个对象
         返回值可以是任意值
####__init__:
class A():
    def __init__(self,name=0):
        print('被调用')
a = A()

####__call__
class A():
    def __init__(self,name=0):
        print('被调用')
    def __call__(self):
        print('两次调用')
a = A()
a()   

####__str__
class A():
    def __init__(self,name=0):
        print('被调用')
    def __call__(self):
        print('两次调用')
    def __str__(self):
        return '你好啊'
a = A()
print(a)

#__getattr__
class A():
    name = 'cegn'
    age =18
    def __getattr__(self,name):
        print('没有啊')
        print(name)
a = A()
print(a.name)
print(a.addr)
结果:
cegn
没有啊
addr
None

#__setattr__案例
class Person():
    def __init__(self):
        pass
    
    def __setattr__(self,name,value):
        print('设置属性:{0}'.format(name))
        #以下语句死循环
        #self.name = value
        #调用父类
        super().__setattr__(name,value)

p = Person()
print(p.__init__)
p.age = 18

#__gt__
class Student():
    def __init__(self,name):
        self._name = name
    
    def __gt__(self,obj):
        print('{0}会比{1}大吗?'.format(self,obj))
        return self._name > obj._name
s1 = Student('one')
s2 = Student('two')     
print(s1 > s2) 
         
####8.类和对象的三种方法         
 -实例方法
   -需要实例化对象才能使用的方法,使用过程中可能需要截止对象的其他对象的方法完成
 -静态方法
   -不需要实例化,通过类直接访问
 -类方法
   -不需要实例化      

#三种方法的案例:
class Person():
    def eat(self):
        print(self)
        print('Eating...')
    #类方法
    #类方法的第一个参数,一般名称cls,
    @classmethod
    def play(cls):
        print(cls)
        print('Playing...')
    
    #静态方法
    #不需要用第一个参数表示自身或者类
    @staticmethod
    def say():
        print('Saying...')
        
yue = Person()
#实例方法
yue.eat()
#类方法
Person.play()
yue.play()
#静态方法
Person.say()
        
#变量的三种用法
class A():
    def __init__(self):
        self.name = 'hha'
        self.age = 18
a = A()
a.name = 'cheng'
print(a.name)        
        
#类属性
#增加一些附加操作        
class A():
    def __init__(self):
        self.name = 'hha'
        self.age = 18  
        #对类变量进行读取操作
    def fget(self):
        print('读取')
        return self.name
    #模拟写操作
    def fset(self):
        print('被写入')
        self.name = 'huhu' + name
    
    def fdel(self):
        pass
    #读。写、删除操作
    name2 = property(fget,fset,fdel,'说明')

a = A()
print(a.name)
print(a.name2)
结果:
hha
读取
hha

##10.抽象类
 -没有具体内容
 -规范子类的行为和借口
 -抽象类的使用需要借助ABC模块
 -抽象类的使用:
     --抽象类可以包含抽象方法,也可以包含具体方法
     --可以有方法也可以有属性
     --不允许直接实例化
     --必须继承才可以使用,必须实现所有继承来的抽象方法
     --如果子类没有实现所有继承的抽象方法,则子类也不能实例化
     --主要作用是设定类的标准,以便开发具有统一的规范
     
    

 #抽象类的实现
import abc
  #声明一个类并且制定当前类的元类
class Human(metaclass=abc.ABCMeta)
    #定义一个抽象方法
    @abc.abstractmethod
    def smoking(self):
        pass
    
    #定义类的抽象方法
    @abc.abstractclassmethod
    def drink():
        pass
    
    #定义静态抽象方法
    @abc.abstractclassmethod
    def play():
        pass
    
    def sleep(self):
        print('Sleeping....')

####自定义类
 -类其实是一个类定义和各种方法的自由组合
 -可以定义类和函数,然后自己通过类直接赋值
 -可以借助MethodType实现
 -借助type实现
 -利用元类实现-MetaClass
  

#函数名当做变量使用
def sayHello(name):
    print('{0}你好,一起玩?'.format(name))
    
sayHello('月月')
liu  = sayHello
liu('yue')
结果:
月月你好,一起玩?
yue你好,一起玩?

#自己组装一个类
class A():
    pass
def say(self):
    print('Saying...')

A.say = say
a = A()
a.say()
结果:
Saying...        
#自己组装一个类2
from types import MethodType
class A():
    pass
def say(self):
    print('Saying...') 

a = A()
a.say = MethodType(say,A)
a.say()
结果:
Saying...  

#利用type造一个类
def say(self):
    print('Saying...')
def talk(self):
    print('Talking...')
 
 #用type来创建一个类
A = type('Aname',(object,),{'class_say':say,'class_talk':talk})
a = A()
a.class_say()
a.class_talk()
结果:
Saying...
Talking...
#元类演示
 #元类写法固定,必须继承type
 #一般命名以MetaClass结尾
class TulignMetaClass(type):
    def __new__(cls,name,bases,attrs):
        return type.__new__(cls,name,bases,attrs)
 #元类定义完就可以使用    


##################`
-定义一个学生类,用来形容学生
class Student():
    pass #此处必须有pass
 -定义一个对象
ming = Student()

-定义一个类,用来描述听python的学生
class PythonStudent():
    name = None
    age = 18
    course = 'Python'
    
    def DoHomeWork(self):
        print('做作业')
        return None #推荐使用

 -实例化
ming = PythonStudent()
print(ming.name)
ming.DoHomeWork()

class A():
    name = 'wang'
    age = 16
A.__dict__
结果:
mappingproxy({'__dict__': <attribute '__dict__' of 'A' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'A' objects>,
              'age': 16,
              'name': 'wang'})


class Student():
    name = 'None'
    age = 20
yueyue = Student()
yueyue.__dict__
结果:
{}

class A():
    name = 'cheng'
    age = 18
    
    def say(self):
        self.name = 'bbb'
        self.age = 200
        
 -类实例的属性和其对象的实例的属性在不对对象的实例属性赋值的情况下,指向同一个值       
 -此时,A成为类实例      
print(A.name)
print(A.age)
print(id(A.name))
print(id(A.age))
结果:
cheng
18
1852383614880
1370714112

a = A()

print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
结果:
cheng
18
1852383614880
1370714112

--5.1
class Student():
    name = 'cheng'
    age = 18
    
    def say(self):
        self.name = 'bbb'
        self.age = 200
        print('My name is {0}'.format(self.name))
        print('My age is {0}'.format(self.age))
        
yue= Student()
yue.say()        
结果:
My name is bbb
My age is 200

--5.3
class Teacher():
    name = 'cheng'
    age = 18
    
    def say(self):
        self.name = 'bbb'
        self.age = 200
        print('My name is {0}'.format(self.name))
        --调用类的成员变量需要用__class__
        print('My age is {0}'.format(__class__.age))
    
    def sayAgain():
        --print(__class__.name)
        print('to me')

t = Teacher()
t.say()
 -调用绑定类函数使用类名
Teacher.sayAgain()
结果:
My name is bbb
My age is 200
to me

My name is bbb
My age is 18
cheng
to me
   
--self案例
class A():
    name = 'ff'
    age = 50
    
    def __init__(self):
        self.name = 'ww'
        self.age = 100
        
    def say(self):
        print(self.name)
        print(self.age)

class B():
    name = 'pppp'
    age = 150

a = A()
 --此时,系统会默认把a作为第一个参数传入函数
a.say()
结果:
ww
100

 -此时,self被a替换
A.say(a)
结果:
ww
100
 
 -同样可以把A作为参数传入
A.say(A)
结果:
ff
50

 -此时,传入类实例B,因为B具有name和age属性
A.say(B)
结果:
pppp
150
 
--6.1私有变量案例
class Person():
    name = 'cheng' #公有
    __age = 18     #私有

p = Person()
print(p.name)
print(p.__age)
   
####继承
class Person():
    name = 'cheng'
    age = 5
    def sleep(self):
        print('Sleep ...')

class Teacher(Person):
    pass

t = Teacher()
print(t.name)
print(Teacher.name)
结果:
cheng
cheng   


class Person():
    name = 'cheng'
    age = 5
    __score = 0
    _petname = 'dddd'
    def sleep(self):
        print('Sleep ...')
    
    def work(self):
        print('make money')

class Teacher(Person):
    teacher_id = '9527'
    name = 'zhi'
    def make_test(self):
        print('attention')
    
    def work(self):
        #Person.work(self)
        super().work() #代表得到父类
        self.make_test()

t = Teacher()
print(t.name)
t.work()
结果:
zhi
make money
attention
   
###构造函数的概念
class Dog():
    def __init__(self):
        print('I am a dog')

kaka = Dog()
结果:
I am a dog

####继承中的构造函数
class Animel():
    def __init__(self):
        print('I am animel')

class PaxingAni(Animel):
    def __init__(self):
        print('PAxing Dongwu')

class Dog(PaxingAni):
    def __init__(self):
        print('I am a dog')
 #实例话的时候,自动调用Dog的构造函数
kaka = Dog()

class Cat(PaxingAni):
    pass
 -没有调用构造函数,自动查找父类
c = Cat()
结果:
PAxing Dongwu

--构造函数--3
class Animel():
    def __init__(self):
        print('I am animel')

class PaxingAni(Animel):
    def __init__(self,name):
        print('PAxing Dongwu {0}'.format(name))

class Dog(PaxingAni):
    def __init__(self):
        print('I am a dog')   
   
d = Dog()   

--因为PaxingAni的构造有2个值,则会报错  
class Cat(PaxingAni):
    pass  
c = Cat()   

class A():
    pass
class B(A):
    pass

print(A.__mro__)
print(B.__mro__)


#单继承与多继承
class Fish():
    def __init__(self,name):
        self.name = name
    
    def swim(self):
        print('I am swimming...')
        
class Bird():
    def __init__(self,name):
        self.name = name
    
    def fly(self):
        print('I am flying...')
        
class Person():
    def __init__(self,name):
        self.name= name
    
    def word(self):
        print('Working...')
        
class Superman(Person,Bird,Fish):
    def __init__(self,name):
        self.name = name

        
s = Superman('yue')
s.fly()
s.swim()
结果:
I am flying...
I am swimming...

####Minxin案例
class Person():
    name = 'cheng'
    age = 18
    
    def eat(self):
        print('Eating...')
        
    def drink(self):
        print('drinking...')
        
    def sleep(self):
        print('Sleeping...')
    
class Teacher(Person):
    def work(self):
        print('Working...')
        
class Student(Person):
    def study(self):
        print('Studying...')
    
class Tutor(Teacher,Student):
    pass

t = Tutor()
print(Tutor.__mro__)
print(t.__dict__)
print(Tutor.__dict__)

class TeacherMixin():
    def work(self):
        print('Working...')
        
class StudentMixin():
    def study(self):
        print('Studying...')
    
class TutorM(Person,TeacherMixin,StudentMixin):
    pass

t = TutorM()
print(Tutor.__mro__)
print(t.__dict__)
print(Tutor.__dict__)

####累的函数
class A():
    pass

class B(A):
    pass

class C():
    pass

print(issubclass(B,A))
结果:
True

class A():
    pass

a = A()
print(isinstance(a,A))

class A():
    name = 'cheng'
a = A()
print(hasattr(a,'name'))

####7.属性案例
class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    
    def intro(self):
        print('I am {0}'.format(self.name))
    
    def detname(self,name):
        self.name = name.upper()
        
s1 = Student('LI',18)
s2 = Student('wang',19)
s1.intro()
s2.intro()


##property案例
class Person():
    def fget(self):
        return self._name * 2
    
    def fset(self,name):
        self._name = name.upper()
    
    def fdel(self):
        self._name = 'NOname'
    name =property(fget,fset,fdel,'UUUU')

p1 = Person()
p1.name = 'opop'
print(p1._name)

发布了89 篇原创文章 · 获赞 109 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/c1z2w3456789/article/details/94880137
OOP