面向对象


一、 面向对象介绍

"""
1、面向过程编程
    核心是过程二字,过程指的是解决的步骤,即先干啥、再干啥、后干啥
    基于该思想写程序就在设计一条条的流水线

    优点:复杂的问题流程化、进而简单化
    缺点:牵一发而动全身,扩展差

2、面向对象编程
    核心是“对象”二字,对象指的是盛放相关的数据与功能的容器
    基于该思想编写程序就在创造一个个的容器来把相关的东西盛到一起

    优点:扩展性强
    缺点:加大了编程的复杂度
"""

二、 类与对象

# 类定义阶段发生的三件事
# 1、会执行类体的代码
# 2、会产生一个类的名称空间,用来将类体代码运行过程中产生的名字都丢进去
# 3、将名称空间的内存地址绑定给类名


# 调用类也发生了三件事
# 1、会创建空对象(调用__new__方法来创建的空对象)
# 2、会自动触发类中__init__函数的运行,__init__(空对象,,"egon",18,"male"),完成对象的初始化操作,注意:__init__不能有返回值
# 3、返回该对象,赋值给stu1_dic

在这里插入图片描述

需要强调的是:在程序中,必须要事先定义类,然后再调用类产生对象(调用类拿到的返回值就是对象)。产生对象的类与对象之间存在关联,这种关联指的是:对象可以访问到类中共有的数据与功能,所以类中的内容仍然是属于对象的,类只不过是一种节省空间、减少代码冗余的机制,面向对象编程最终的核心仍然是去使用对象。

三、 类的定义与实例化

# 版本1:
"""
class Student:
    school = "SH"

    def choose_course(stu_dic, course):
        stu_dic["courses"].append(course)
        print('学生 %s 选课成功 %s' % (stu_dic["name"], stu_dic["courses"]))



# 调用类
stu1_dic = Student()
stu2_dic = Student()

stu1_dic.name = "egon"        # stu1_dic.__dict__["name"] = "egon"
stu1_dic.age = 18             # stu1_dic.__dict__["age"] = 18
stu1_dic.gender = "male"      # stu1_dic.__dict__["gender"] = "male"
stu1_dic.courses = []         # stu1_dic.__dict__["courses"] = []


stu2_dic.name = "tom"
stu2_dic.age = 38
stu2_dic.gender = "female"
stu2_dic.courses = []


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

print(stu1_dic.__dict__)
print(stu2_dic.__dict__)
print(Student.__dict__)

print(stu1_dic.name)
"""


# 版本2:
class Student:
    school = "SH"

    def choose_course(stu_dic, course):
        stu_dic["courses"].append(course)
        print('学生 %s 选课成功 %s' % (stu_dic["name"], stu_dic["courses"]))



# 调用类
stu1_dic = Student()
stu2_dic = Student()


def init(stu_dic, name, age, gender, courses=None):
    if courses is None:
        courses = []
    stu_dic.name = name
    stu_dic.age = age
    stu_dic.gender = gender
    stu_dic.courses = courses

init(stu1_dic,"egon",18,"male")
init(stu2_dic,"tom",38,"female")


print(stu1_dic.__dict__)
print(stu2_dic.__dict__)
print(Student.__dict__)

# 版本3:
class Student:
    school = "SH"
    #            空对象,,"egon",18,"male")
    def __init__(stu_dic, name, age, gender, courses=None):
        if courses is None:
            courses = []
        stu_dic.name = name
        stu_dic.age = age
        stu_dic.gender = gender
        stu_dic.courses = courses
        # return None

    def choose_course(stu_dic, course):
        stu_dic["courses"].append(course)
        print('学生 %s 选课成功 %s' % (stu_dic["name"], stu_dic["courses"]))


# 类定义阶段发生的三件事
# 1、会执行类体的代码
# 2、会产生一个类的名称空间,用来将类体代码运行过程中产生的名字都丢进去
# 3、将名称空间的内存地址绑定给类名


# 调用类也发生了三件事
# 1、会创建空对象(调用__new__方法来创建的空对象)
# 2、会自动触发类中__init__函数的运行,__init__(空对象,,"egon",18,"male"),完成对象的初始化操作,注意:__init__不能有返回值
# 3、返回该对象,赋值给stu1_dic
stu1_dic = Student("egon",18,"male")
stu2_dic = Student("tom",38,"female")




print(stu1_dic.__dict__)
print(stu2_dic.__dict__)
print(Student.__dict__)

四、 属性查找

1、类属性与对象属性

在类中定义的名字,都是类的属性,细说的话,类有两种属性:数据属性函数属性,可以通过__dict__访问属性的值,比如Student.dict[‘school’],但Python提供了专门的属性访问语法


>>> Student.school # 访问数据属性,等同于Student.__dict__['school']
'清华大学'
>>> Student.choose # 访问函数属性,等同于Student.__dict__['choose']
<function Student.choose at 0x1018a2950>
# 除了查看属性外,我们还可以使用Student.attrib=value(修改或新增属性),用del Student.attrib删除属性。

操作对象的属性也是一样

>>> stu1_dic.name # 查看,等同于obj1.__dict__[‘name']
'李建刚'
>>> stu1_dic.course=’python’ # 新增,等同于obj1.__dict__[‘course']='python'
>>> stu1_dic.age=38 # 修改,等同于obj1.__dict__[‘age']=38
>>> del obj1.course # 删除,等同于del obj1.__dict__['course']

2、 属性查找顺序与绑定方法

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

  1. 类中定义的变量是类的数据属性,是共享给所有对象用的,指向相同的内存地址
# id都一样
print(id(Student.school)) # 4301108704

print(id(stu1_dic.school)) # 4301108704
print(id(stu2_dic.school)) # 4301108704
print(id(stu3_dic.school)) # 4301108704
  1. 类中定义的函数是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数
Student.choose(stu1_dic) # 李建刚 is choosing a course
Student.choose(stu2_dic) # 王大力 is choosing a course
Student.choose(stu3_dic) # 牛嗷嗷 is choosing a course

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

print(id(Student.choose)) # 4335426280

print(id(stu1_dic.choose)) # 4300433608
print(id(stu2_dic.choose)) # 4300433608
print(id(stu3_dic.choose)) # 4300433608

绑定到对象的方法特殊之处在于,绑定给谁就应该由谁来调用,谁来调用,就会将’谁’本身当做第一个参数自动传入(方法__init__也是一样的道理)

stu1_dic.choose()  # 等同于Student.choose(stu1)
stu2_dic.choose()  # 等同于Student.choose(stu2)
stu3_dic.choose()  # 等同于Student.choose(stu3)

绑定到不同对象的choose技能,虽然都是选课,但李建刚选的课,不会选给王大力,这正是”绑定“二字的精髓所在。

'''
注意:绑定到对象方法的这种自动传值的特征,决定了在类中定义的函数都要默认
写一个参数self,self可以是任意名字,但命名为self是约定俗成的。
'''

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']

总结

"""
类中定义的函数分为两大类

一:绑定方法:绑定给谁就应该由谁来调用,谁来调用就会将自己当作第一个参数自动传入
绑定给对象

绑定给类

二:非绑定方法:不与任何人绑定,意味着谁都可以来调用,但是无论谁来调用就是一个普通函数,没有自动传参的效果


"""

五、绑定方法与非绑定方法

类中定义的函数分为两大类:绑定方法和非绑定方法

​ 其中绑定方法又分为绑定到对象的对象方法和绑定到类的类方法。

​ 在类中正常定义的函数默认是绑定到对象的,而为某个函数加上装饰器@classmethod后,该函数就绑定到了类。

# 配置文件settings.py的内容
HOST='127.0.0.1'
PORT=3306

# 类方法的应用
import settings
class MySQL:
    def __init__(self,host,port):
        self.host=host
        self.port=port
    @classmethod
    def from_conf(cls): # 从配置文件中读取配置进行初始化
        return cls
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值