面向对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象相关的知识,希望对你有一定的参考价值。

面向对象与面向过程

面向过程:核心是过程二字,过程指的是问题的解决步骤,即先干什么在干什么,基于面向对象去设计程序好比在涉及一跳流水线,是一种
机械的思维方式
优点:复杂的问题流程化,进而简单化
缺点:可扩展性差,多用于脚本程序,linux系统管理脚本,linux内核,httpdgit
面向对象:核心是对象二字,对象就是特征与技能的结合体,如果把涉及程序比喻成创造一个世界,那你就是这个世界的上帝
,与面向过程对机械流水的模拟形式鲜明对比面向对象更注重的对现实的世界的模拟
优点:扩展性强
类即种类,类别,对象是特征和技能的结合体,那么类就是一系列对象相似的特征与技能的结合体
在现实世界中:先有一个个具体存在的对象---》(总结相似之处)---》现实中的类
在程序中:一定是先定义类,后调用类来产生对象

第一阶段:现实中的对象----》现实中类
obj1:
特征
学校 = oldboy
名字= a
年龄 = 18
技能
吃饭
学习
obj1:
特征
学校 = oldboy
名字= b
年龄 = 18
技能
吃饭
学习

现实中的老男孩学生类:
相似的特征
学校 = oldboy
相似的技能
学习
吃饭
第二阶段:程序中的类----》程序中的对象
class OldboyStudent:
    school  = oldboy#类的数据属性
    def learn(self):#类的函数属性
        print(is learning)

#类体的代码在类定义阶段就会执行,理所应当会产生类的名称空间,用__dict__属性查看,类的__dict__字典不允许修改
print(OldboyStudent.__dict__)
#{‘__doc__‘: None, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘OldboyStudent‘ objects>, ‘school‘: ‘oldboy‘, ‘__dict__‘: <attribute ‘__dict__‘ of ‘OldboyStudent‘ objects>, ‘learn‘: <function OldboyStudent.learn at 0x01E75FA8>, ‘__module__‘: ‘__main__‘}
print(OldboyStudent.__dict__[school])
#oldboy

#类的属性操作
print(OldboyStudent.school)#类中的变量
#oldboy
print(OldboyStudent.learn)#类中的函数
#<function OldboyStudent.learn at 0x01D95FA8>
OldboyStudent.learn(123)
#is learning
OldboyStudent.x = 111111111
OldboyStudent.school= Oldboy
del OldboyStudent.school
print(OldboyStudent.__dict__)
#{‘__dict__‘: <attribute ‘__dict__‘ of ‘OldboyStudent‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘OldboyStudent‘ objects>, ‘x‘: 111111111, ‘learn‘: <function OldboyStudent.learn at 0x01D95FA8>, ‘__module__‘: ‘__main__‘, ‘__doc__‘: None}
OldboyStudent.__dict__[x] = 111111111#会报错,不允许__dict__修改方式
 #对象的创建相同的特性放在类中,不同的特性放在__init__中
class OldboyStudent:
    school=oldboy#类的数据属性
    #obj1,‘李坦克‘,‘男‘,18
    def __init__(self,name,age,sex):#类的函数属性,在实例化时,产生对象之后执行
        self.name=name
        self.age=age
        self.sex=sex
        #obj1.name = name
        #obj1.age = age
        #obj1.sex = sex
    def learn(self):
        print(%s is learning %self.name) #新增self.name

    def eat(self):
        print(%s is eating %self.name)

    def sleep(self):
        print(%s is sleeping %self.name)
#类体在定义阶段就会执行理所应当会产生类的名称空间,用__dict__属性查看
#产生程序中的对象:类名加括号,调用类,产生一个该类的实例存在的对象,该调用过程称为实例化
#产生对象分两步:第一步:先产生一个空对象obj1
#第二部:OldboyStudent.__init__(obj1,‘李坦克‘,‘男‘,18)
#使用print(obj1.__dict__)查看对象的名称空间
obj1=OldboyStudent(李坦克,,18)
obj2=OldboyStudent(王大炮,,38)
obj3=OldboyStudent(牛榴弹,,78)

#对象可以访问类的数据属性,结论:类的苏剧属性共享给所有对象使用,id一样
print(obj1.school,id(obj1.school))
print(obj2.school,id(obj2.school))
print(obj3.school,id(obj3.school))
#oldboy 18308000
#oldboy 18308000
#oldboy 18308000

print(obj1.learn)#对象绑定方法
#<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x01175B50>>
print(obj2.learn)
#<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x01175B50>>
print(obj3.learn)
#<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x01175B50>>
print(OldboyStudent.learn)#类的函数
#<function OldboyStudent.learn at 0x00A656F0>

#绑定方法:绑定给谁,就有谁来调用,谁来调用就把谁当作第一参数传入
obj1.learn()#OldboyStudent.learn(obj1)
#李坦克 is learning
obj2.learn()
#王大炮 is learning
obj3.learn()
#牛榴弹 is learning

基础小练习

#对象计数,每产生一个对象加1
class Foo:
    count = 0
    def __init__(self,x):
        self.x = x
        Foo.count += 1

obj1 = Foo(1)
obj2 = Foo(2)

print(obj1.count)

类之间的交互


class Garen:
  camp = Demacia
    #                  别名,   血量               攻击
    def __init__(self,nickname,life_value = 100,aggresivity = 80):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attack(self,enemy):#攻击函数
        enemy.life_value-= self.aggresivity

class Riven:
    camp = Noxus
    #                  别名,   血量               攻击
    def __init__(self,nickname,life_value = 80,aggresivity = 100):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attack(self,enemy):#攻击函数
        enemy.life_value-= self.aggresivity

g1 = Garen(草丛猥琐男)
r1 = Riven(兔女郎)
print(r1.life_value)#瑞文的血量
#80
g1.attack(r1)#将r1对象传入g1的attack函数中 print(r1.life_value)
#0

继承

什么是继承

继承指的是类与类之间的关系,是一种什么是什么的关系,功能之一就是用来解决代码重用问题(比如练习7中Garen与Riven类有很多冗余的代码)

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。

 

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

#查看继承关系
>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class __main__.ParentClass1>,)
>>> SubClass2.__bases__
(<class __main__.ParentClass1>, <class __main__.ParentClass2>)

 

 

 

class Animal:
    x = 1000
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def talk(self):
        print(=====>)

class People(Animal):#继承类可省略
    x = 10
    def __init__(self,name,age,sex,education):
        Animal.__init__(self,name,age,sex)#指名道姓调用法
        self.education = education

    def talk(self):
        Animal.talk(self)
        print(这是人在说话)

peo1  = People(wate,18,male,小学肄业)
print(peo1.__dict__)#对象的名称空间
#{‘age‘: 18, ‘name‘: ‘wate‘, ‘education‘: ‘小学肄业‘, ‘sex‘: ‘male‘}
peo1.talk()
#=====>这是人在说话
print(peo1.x)#名称空间的查找,1、先查找自己方法中的,2、查找自己类中的,3、查找父类中的,调用关系与位置无关
#10
class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print(%s is eating%self.name)


class OldboyTeacher(People):
    def __init__(self,name,age,sex,salary,title):
        People.__init__(self,name,age,sex)
        self.salary = salary
        self.title = title

    def teach(self):
        print(%s is teaching%self.name)

class OldboyStudent(People):
    def __init__(self,name,age,sex,xuefei):
        People.__init__(self,name,age,sex)#指明道姓法
        self.xuefei = xuefei

    def learn(self):
        print(%s is learning%self.name)

stu1 = OldboyStudent(wate,18,male,5000)
teacher1 = OldboyTeacher(egon,18,mail,100,沙河一霸)
stu1.eat()
#wate is eating stu1.learn()
#wate is learning teacher1.teach()
#egon is teaching

总结:
1 、 继承的功能之一:解决类与类之间的代码重复问题
2 、 继承是类与类之间的关系,是一种,什么是什么的关系(人是动物,猪是动物)
3 、 在子类派生出新的属性,已自己的为准
4 、 在子类派出的新的方法中重用父类的功能的方式:指名道姓调用
OldboyPeople.__init__
这种调用方式本身与继承是没有关系的

 

组合

软件重用的重要方式除了继承之外还有另外一种方式,即:组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

class OldboyPeople:
    ‘‘‘
    老师与学生父类
    ‘‘‘
    school = oldboy
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eat(self):
        print(is eating)

class OldboyStudent(OldboyPeople):
    ‘‘‘
    学生类
    ‘‘‘
    def __init__(self,name,age,sex):
        OldboyPeople.__init__(self,name,age,sex)
        self.course= []#另外一个类的对象作为数据属性保存在course中
    def learn(self):
        print(%s is learning % self.name)

class OldboyTeacher(OldboyPeople):
    ‘‘‘
    教师类
    ‘‘‘
    def __init__(self,name,age,sex,salary,title):
        OldboyPeople.__init__(self,name,age,sex)# 相当于super().__init__(self,name,age,sex)
        self.salary = salary
        self.title = title
        self.course= []#为教师保存课程对象
    def learn(self):
        print(%s is learning % self.name)

class Course:
    def __init__(self,course_name,course_period,course_price):
        self.course_name=course_name
        self.course_period=course_period
        self.course_price=course_price
    def tell_info(self):
        print(<课程名:%s 周期:%s 价格:%s> %(self.course_name,self.course_period,self.course_price))
#添加课程
python=Course(Python,6mons,3000)
linux=Course(Lnux,3mons,2000)
bigdata=Course(BigData,1mons,1000)

#添加老师对象
egon_obj=OldboyTeacher(egon,18,male,3.1,沙河霸道金牌讲师)
#为老师添加课程
egon_obj.course.append(python)
egon_obj.course.append(linux)
for obj in egon_obj.course:
    obj.tell_info()
#<课程名:Python 周期:6mons 价格:3000>
#<课程名:Lnux 周期:3mons 价格:2000>

#创建学生类
yl_obj=OldboyStudent(yanglei,28,female)
yl_obj.course.append(python)

for i in yl_obj.course:
    # print(i.course_name,i.course_period,i.course_price)
    i.tell_info()
#<课程名:Python 周期:6mons 价格:3000>

绑定方法与非绑定方法

一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

    1. 绑定到类的方法:用classmethod装饰器装饰的方法。

                为类量身定制

                类.boud_method(),自动将类当作第一个参数传入

    2. 绑定到对象的方法:没有被任何装饰器装饰的方法。

               为对象量身定制

               对象.boud_method(),自动将对象当作第一个参数传入

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

        1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

    注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

#setting.py
Port = 3306
Host = 127.0.0.1
import setting

class mysql:
    def __init__(self,host,port):
        self.host = host
        self.port = port

    @classmethod
    def from_conf(cls):
        return cls(setting.Host,setting.Port)


res = Mysql.from_conf()#不需要实例化对象,直接用类调用执行
print(res.host,res.port)
#127.0.0.1 3306

 

以上是关于面向对象的主要内容,如果未能解决你的问题,请参考以下文章

224 面向对象编程介绍,面向过程与面向对象

面向对象-面向对象和面向过程的区别

面向对象分析与设计面向对象设计包括哪些内容

面向对象

面向过程面向对象及面向对象的三大特征

Python面向对象学习 1 (什么是面向对象,面向对象的应用场景)