面向对象编程

一 对象的概念

  面向对象“的核心是“对象”二字,而对象的精髓在于“整合“

  所有的程序都是由”数据”与“功能“组成,因而编写程序的本质就是定义出一系列的数据,然后定义出一系列的功能来对数据进行操作。在学习”对象“之前,程序中的数据与功能是分离开的,

  

  在学习了“对象”之后,我们就有了一个容器,该容器可以盛放数据与功能,所以我们可以说:对象是把数据与功能整合到一起的产物,或者说”对象“就是一个盛放数据与功能的容器/箱子/盒子。

  面向对象编程就是要造出一个个的对象,把原本分散开的相关数据与功能整合到一个个的对象里

  优点:方便使用,提高程序的解耦合程度,提升了程序的可扩展性

二 类

  在学习面向对象编程之前我们还要先知道类的概念

  2.1 什么是类

    类即类别/种类,是面向对象分析和设计的基石,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。

    如果多个对象有相似的数据与功能,那么该多个对象就属于同一种类。

                                                                                          类

三 面向对象编程

  3.1 类的定义

    面向对象的基本思路就是把程序中要用到的、相关联的数据与功能整合到对象里,然后再去使用,我们举个例子

# 学生1:
    数据:
        学校=清华大学
        姓名=李建刚
        性别=男
        年龄=28
    功能:
        选课

# 学生2:
    数据:
        学校=清华大学
        姓名=王大力
        性别=女
        年龄=18
    功能:
        选课

# 学生3:
    数据:
        学校=清华大学
        姓名=牛嗷嗷
        性别=男
        年龄=38
    功能:
        选课

    首先我们可以定义一个类

class Student:
    school = '清华'

    # 2、功能的定义
    def tell_stu_info(stu_obj):
        print('学生信息:名字:%s 年龄:%s 性别:%s' %(
            self.stu_name,
            self.stu_age,
            self.stu_gender
        )) 

    def choose(self): print('%s is choosing a course' %self.name)                            

    类体中最常见的是变量与函数的定义,但是类体其实是可以包含任意其他代码的

    注意:类体代码是在类定义阶段就会立即执行,会产生类的名称空间

    可以打印Student.__dict__来查看类这个容器内盛放的东西

  3.2 类的调用再产生对象

stu1_obj=Student() #没调用一次类就会产生一个学生对象
stu2_obj=Student()
stu3_obj=Student()

    如此stu1_obj、stu2_obj、stu3_obj全都一样了(只有类中共有的内容,而没有各自独有的数据),想在调用的过程中就为三位学生定制各自独有的数据:姓名,性别,年龄,需要我们在类内部新增一个__init__方法,如下

class Student:
    school = '清华'

    def __init__(obj,x,y,z):
        obj.stu_name=x 
        obj.stu_age=y  
        obj.stu_gender=z 
        # return None

    # 2、功能的定义
    def tell_stu_info(stu_obj):
        print('学生信息:名字:%s 年龄:%s 性别:%s' %(
                self.stu_name,
                self.stu_age,
                self.stu_gender
        ))
        
    def choose(self): 
        print('%s is choosing a course' %self.name)

     关于_init_方法 

    1、会在调用类时自动触发执行,用来为对象初始化自己独有的数据

    2、__init__内应该存放是为对象初始化属性的功能,但是是可以存放任意其他代码,想要在类调用时就立刻执行的代码都可以放到该方法内

    3、__init__方法必须返回None

stu1_obj=Student('egon',18,'male')
stu2_obj=Student('lili',19,'female')

print(stu1_obj.__dict__)
print(stu2_obj.__dict__)

# {'stu_name': 'egon', 'stu_age': 18, 'stu_gender': 'male'}
# {'stu_name': 'lili', 'stu_age': 19, 'stu_gender': 'female'}

     调用类的过程发生了三件事

    1、先产生一个空对象

    2、python会自动调用类中的__init__方法然将空对象已经调用类时括号内传入的参数一同传给__init__方法

    3、返回初始完的对象

    单拿stu1_obj的产生过程来分析,调用类会先产生一个空对象stu1_obj,然后将stu1_obj连同调用类时括号内的参数一起传给Student.__init__(stu1_obj,’egon’,18,;male')

  3.3 属性的访问

    在类中定义的名字,都是类的属性,细说的话,类有两种属性:数据属性和函数属性。

    可以通过__dict__访问属性的值,比如Student.__dict__[‘school’],但Python提供了专门的属性访问语法

Student.school # 访问数据属性,等同于Student.__dict__['school']
Student.choose # 访问函数属性,等同于Student.__dict__['choose']

    同理操作对象的属性也是一样的,除了查看属性外我们还可以修改属性

stu1_obj=Student('egon',18,'male')
print(stu1_obj.__dict__)

print(stu1_obj.stu_name)#查看属性
stu1_obj.course='python' #添加属性
stu1_obj.stu_age = 20 #修改属性
del stu1_obj.stu_gender #删除属性
print(stu1_obj.__dict__)

     属性的访问顺序和查找方法:

    对象的名称空间里只存放着对象独有的属性,而对象们相似的属性是存放于类中的。对象在访问属性时,会优先从对象本身的__dict__中查找,未找到,则去类的__dict__中查找

    

    1、类的数据属性是共享给所有对象用的,大家访问的地址都一样

print(id(Student.school))# 2493299721864
print(id(stu1_obj.school))# 2493299721864
print(id(stu2_obj.school))# 2493299721864

    因此当类中的变量的值改变时对象中的也会跟着改变

Student.school='OLDBOY'
print(stu1_obj.school)#OLDBOY

    2、类中定义的函数主要是给对象使用的,而且是绑定给对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法,内存地址各不相同

print(id(Student.choose)) # 4335426280

print(id(stu1_obj.choose)) # 4300433608
print(id(stu2_obj.choose)) # 4300433608

    类调用自己的函数属性必须严格按照函数的用法来

Student.tell_stu_info(stu1_obj)
Student.tell_stu_info(stu2_obj)

    绑定方法的特殊之处在于:谁来调用绑定方法就会将谁当做第一个参数自动传入

stu1_obj.tell_stu_info() #Student.tell_stu_info(stu1_obj)
stu2_obj.tell_stu_info() #Student.tell_stu_info(stu2_obj)

    强调一点:因为python底层代码规定,在类中定义函数时必须要在括号内定义一个变量来接收传入的对象

四 总结

  Python中一切皆为对象,且Python3中类与类型是一个概念,因而绑定方法我们早就接触过

#类型list就是类
>>> list
<class 'list'>

#实例化的到3个对象l1,l2,l3
>>> l1=list([1,2,3])
>>> l2=list(['a','b','c'])
>>> l3=list(['x','y'])

#三个对象都有绑定方法append,是相同的功能,但内存地址不同
>>> l1.append
<built-in method append of list object at 0x10b482b48>
>>> l2.append
<built-in method append of list object at 0x10b482b88>
>>> l3.append
<built-in method append of list object at 0x10b482bc8>

#操作绑定方法l1.append(4),就是在往l1添加4,绝对不会将4添加到l2或l3
>>> l1.append(4) #等同于list.append(l1,4)
>>> l1
[1,2,3,4]
>>> l2
['a','b','c']
>>> l3
['x','y']

  在上述介绍类与对象的使用过程中,我们更多的是站在底层原理的角度去介绍类与对象之间的关联关系,如果只是站在使用的角度,我们无需考虑语法“对象.属性"中”属性“到底源自于哪里,只需要知道是通过对象获取到的就可以了,所以说,对象是一个高度整合的产物,有了对象,我们只需要使用”对象.xxx“的语法就可以得到跟这个对象相关的所有数据与功能,十分方便且解耦合程度极高。

原文地址:https://www.cnblogs.com/bk134/p/12652223.html