首页 > 技术文章 > 面向对象总结

wanglan 2018-11-27 20:51 原文

基础概念

静态属性\私有属性

class Person(object):
    COUNTRY = '牧师' #静态属性
    __MAGE = '法师'  # 私有静态属性,只能在类的内部使用,外部无法直接操作
    def __init__(self,name,age): #self是一块内存空间,实例化后会存放属性的值
        self.name = name #属性,属于对象的值 --对象属性
        self.__age = age #对象的私有属性 ,私有属性不能被继承,只能在类的内部使用,外部无法直接操作
    def running(self): #类的方法,方法自带self参数,动态属性
        print('%s running'%self.name) #使用对象属性
        print(self.__age) #使用对象的静态属性
print(Person.COUNTRY) #查看类的静态属性 类名.静态属性名
ret = Person('wanglan',18) #ret:对象  实例化
print(ret.name) #使用对象查看对象属性
ret.running() #使用对象调用类中的方法

概念

什么是类:具有相同属性和方法的一类事事物
什么是对象:对象是类中一个具体的例子(拥有具体的属性值和具体的方法),对象就是类的实例化,类的实例
什么是实例:实例完全和对象是一样的
什么是实例化:由类创建对象的过程
实例化的过程:1.创建一个属于对象的空间  2.将这个空间的地址和参数传递给__init__方法 3.执行init方法,4.将对象的空间返回给对象名
静态属性:所有的这个类的对象都共有的属性
什么是对象的属性:存储在实例化之后创建的空间中的所有变量都是对象的属性,每一次实例化产生的空间都是独立的,每一个对象都有自己的属性值
对象能做什么:调用对象的属性,调用类中的方法(动态属性)
什么是动态属性:定义在类中的函数,自带一个self属性
类中的代码在实例化之前执行
类的命名空间中有静态属性和动态方法

__dict__

class Person(object):
    NAME = 'WL'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print(self.name)
        print(self.age)
person = Person('wanglan','18')
print(Person.__dict__) #类名.__dict__,查看类中的变量,属性,不能操作,只能查看
print(person.__dict__) #对象名.__dict__会将对象属性和值以字典的方式打印出来
print(person.__dict__['name']) #取值

操作属性的值

class Person(object):
    NAME = 'WL'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print(self.name)
        print(self.age)
person = Person('wanglan','18')
#查看属性值
print(person.name)
# 修改属性的值
person.name = 'wl'
print(person.name)
#添加一个属性
person.gender = ''
print(person.gender)
#删除属性的值
del person.gender
print(person.gender)

对象之间的交互

class Dog:
    def __init__(self,name,kind,hp,ad):
        self.name = name
        self.kind = kind
        self.hp = hp
        self.ad = ad
    def bite(self,person):
        print('%s咬人%s'%(self.name,person.name))
        person.hp -= self.ad
        if person.hp <= 0 :
            print('%s死了'%person.name)
            person.hp = 0
# 实例化一些对象
xm = Person('xiaoming','',10,10,100)
eh = Dog('二哈','金毛',9999,998)
print(eh.hp) #查看二哈的hp
xm.attack(eh) #小明攻击了二哈,
print(eh.hp) # 再次查看二哈的hp
print(xm.hp) #查看小明的hp
eh.bite(xm) #二哈咬了小明
print(xm.hp) #再次查看小明的hp

一个类中可以没有__init__

class A:
    Country = 'China'
    def talk(self):
        print('%s is talking'%self.name)
xm = A()
xm.name = 'alex'
xm.talk()
# 在没有__init__的情况下,实例化经历了哪些步骤???
# 1.创建一个空间给对象
# 2.将这个空间的地址返回

对象的命名空间和类的命名空间之间的关系 

对象和类之间有一个单向的联系,类对象指针
对象在使用某个名字的时候,如果在自己的空间中没有找到,就要到类的空间中去找
class A:
    Country = 'China' # 静态属性就是用来描述所有的对象都共享的某一个值
    def __init__(self,name):
        self.name = name
    def talk(self):
        print('%s is talking'%self.name)
xiaogao = A('xiaogao')
print(xiaogao.Country)
xiaogao.Country = '泰国'  #在xiaogao中创建,并不是去找静态属性
print(xiaogao.Country)   # '泰国'
del xiaogao.Country
print(xiaogao.Country)   # 'China'
print(A.Country)

对象可以查看类的静态属性,但是不能修改,并且一旦修改,就不能取到类当中的内容了(除非手动删除这个修改的属性),所有的静态属性的修改,都应该由类名来完成,而不应该使用对象名来完成

组合

圆形类/环形类

from math import pi
class Circle:
    def __init__(self,r):
        self.r = r
    def area(self):
        return pi*self.r**2
    def perimeter(self):
        return 2*pi*self.r
c1 = Circle(10)
print(c1.area())
print(c1.perimeter())

class Ring:
    def __init__(self,outer_r,inner_r):
        self.out_c = Circle(outer_r)   # Circle(10)
        self.in_c = Circle(inner_r)   # Circle(5)

    def area(self):
        return self.out_c.area() - self.in_c.area()

    def perimeter(self):
        return self.out_c.perimeter() + self.in_c.perimeter()

r1 = Ring(10,5)
print(r1.area())
print(r1.perimeter())

 

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

class Student:
    def __init__(self,name,sex,birth_day):
        self.name = name
        self.sex = sex
        self.birthday = birth_day

birth = Birthday(1996,9,13)
bobo = Student('bobo','male',birth)
# birth == bobo.birthday
# birth.year
print(bobo.birthday.year)

 pickle :游戏人物状态的保存(存档读档)练习

pickle模块可以序列化python中的所有自定义类的对象

import pickle
class Course:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def __str__(self):
        return ('%s %s %s' %(self.name,self.age,self.gender))
xl = Course('xiaoming',18,'')
print(xl)
with open('courses','wb') as f:
    pickle.dump(xl,f)  #写入文件
with open('courses','rb') as f:
    ret = pickle.load(f)
    print(ret)

如果load一个对象,那么这个对象所对应的类必须已经在内存中
同一个类的对象 会存储在同一个文件中

继承

继承 : 就是为了解决类与类之间代码重复的问题的

类的继承的语法

单继承

class A:pass
class B(A):pass
print(A.__bases__)  #查看父类
print(B.__bases__)

结果:
(<class 'object'>,)    #类默认继承onject
(<class '__main__.A'>,)  #B继承了A

 多继承

class A:pass
class B:pass
class C(A,B):pass
print(A.__bases__)
print(B.__bases__)
print(C.__bases__)

结果:
(<class 'object'>,)
(<class 'object'>,)
(<class '__main__.A'>, <class '__main__.B'>)

子类可以继承父类的方法和属性

子类调用方法,如果子类自己有用自己的,用了自己的就不用父类的了

如果子类自己没有才调用父类的
如果子类有个性化的父类没有的方法,可以单独定义在子类中 - 派生方法
只有子类能够使用父类中的方法,父类不可以使用子类中的方法

 

当某一个方法,父类和子类都拥有的时候,那么在子类的方法中,调用父类的同名方法

1.父类名.方法名(self,...)

2.super().__init__(...)

class Animal:
    def __init__(self,name,hp,ad):
        self.name = name
        self.hp = hp
        self.ad = ad
class Person(Animal):
    def __init__(self,name,sex,hp,mp,ad):
        super().__init__(name,hp,ad)
        self.sex = sex   # 派生属性
        self.mp = mp     # 派生属性

    def attack(self,dog):
        print('%s攻击了%s'%(self.name,dog.name))
        dog.hp -= self.ad

class Dog(Animal):
    def __init__(self,name,kind,hp,ad):
        super().__init__(name,hp,ad)
        self.kind = kind   # 派生属性

    def bite(self,person):
        print('%s咬了%s'%(self.name,person.name))
        person.hp -= self.ad

alex = Person('alex','不详',10,10,0.1)
hei = Dog('小黑','中华田园犬',999,1.1)
print(hei.__dict__)
View Code

归一化/抽象类

from abc  import ABCMeta,abstractmethod #抽象方法
class Payment(metaclass=ABCMeta): #metaclass = ABCMeta表示Payment类是一个规范类
    @abstractmethod  # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
    def pay(self):pass

class AliPay(Payment):
    def __init__(self,name):
        self.name = name
    def pay(self,money):
        # 支付宝提供了一个网络上的联系渠道
        print('%s通过支付宝消费了%s元'%(self.name,money))

class WeChatPay(Payment):
    def __init__(self,name):
        self.name = name
    def pay(self,money):
        # 微信提供了一个网络上的联系渠道
        print('%s通过微信消费了%s元'%(self.name,money))
# 归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本
def pay_func(person,payway,money):
    if payway == 'alipay':
        per = AliPay(person)
    elif payway == 'wechatpay':
        per = WeChatPay(person)
    per.pay(money)
pay_func('WL','wechatpay',200)
View Code

接口类

rom abc import ABCMeta,abstractmethod
class Fly_Animal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        print('爷会飞')
class Swim_Animal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self): pass
class Walk_Animal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self): pass

class Swan(Fly_Animal,Swim_Animal,Walk_Animal):
    def fly(self):
        super().fly()
        print('')
    def walk(self):print('')
    def swim(self):print('')

class Tiger(Walk_Animal,Swim_Animal):
    def walk(self):print('')
    def swim(self):print('')

class Parrot(Fly_Animal,Walk_Animal):
    def fly(self):print('')
    def walk(self):print('')
    def talk(self):print('')
View Code

c3算法

每一个类的继承顺序都是从基类向子类看
形成一个指向关系的顺序[当前类] + [父类的继承顺序]
进行一个提取
如果一个类出现从左到右的第一个顺序上,并且没有出现在后面的顺序中,或者出现在后面顺序了,但是仍然是第一个,那么就把这个类提取出来
View Code

super在多继承中的意义

class A:
    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')

d = D()
d.func()
print(D.__mro__)
View Code

 

推荐阅读