菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
69
0

python之面向对象编程

原创
05/13 14:22
阅读数 31512

一、什么是对象?

1、面向过程编程

    自我们第一次接触编程,就开始学习面向过程编程,面向过程的重点是“过程”。我们在写一个程序时,都会思考,先实现什么,再实现什么,最后实现什么,举个简单的例子:要实现计算1+1,我们要先给程序传入两个值1和1,然后调用程序计算1+1并赋值给变量,最后打印结果,这就是面向过程编程。面向过程编程可以看做是程序的基石。

2、面向对象编程

    什么又是面向对象编程呢?面向对象编程的核心是“对象”。

  • 对象:对象可以形象的理解为容器,用来盛放程序相关的数据与功能。对象就、像是女生的化妆包,化妆需要的“数据”:眼影、粉底、隔离、高光.....,以及需要使用到的工具:美妆蛋、眼影刷、睫毛夹.....都被收集到了一起,化妆时,只需要将化妆包拿出就可以进行相应操作,无需到处翻找化妆的东西。
# 原始方法,按照粉底——腮红——眼妆的顺序,逐个给到数据和定义方法
x = "粉底"
def 美妆蛋():
    print("开始上底妆")


y = "腮红"
def 化妆刷():
    print("开始打腮红")


x = "眼影"
def 眼影刷():
    print("开始画眼妆")




# 面向对象
def 美妆蛋():
    print("开始上底妆")


def 化妆刷():
    print("开始打腮红")


def 眼影刷():
    print("开始画眼妆")


# 这里定义的化妆包字典就是一个对象,包含了化妆这个程序的数据与功能
化妆包 = {
    "化妆品": ["粉底", "腮红", "眼影"],
    "化妆工具": [美妆蛋, 化妆刷, 眼影刷]
}
  • 面向对象编程:面向对象编程就是要造出一个个的对象,把原本分散开的相关数据与功能整合到一个个的对象里,这么做既方便使用,也可以提高程序的解耦合程度,进而提升了程序的可扩展性(需要强调的是,软件质量属性包含很多方面,面向对象解决的仅仅只是扩展性问题)
  • 优缺点:有点就是可以提高程序的解耦合程度,提升程序可扩展性,缺点是会使得程序编程变得复杂,如果不合理的使用,还会造成过度编程。

二、类与对象

1、什么是类?

  通过上诉的例子,我们知道我们有多个方法可以创建对象:列表、字典、集合等,但是我们可以发现使用这些“工具”创建的对象有很多局限,首先是取用还是不太清晰,使用时需要通过key索引取值,其次,我们还需要实现定义方法,查看相应功能不够便利。于是python为广大程序员提供了一种便捷的建立对象的方法,这就需要用到类,使用关键字class创建类,语法如下:

class 类名:
    
    # 定义变量
    x = 1
    ...
    
    # 定义函数,其中的self参数是代表自动传入对象,后续会讲解,这里可以忽略
    def f1(self):
        pass
    
    def f2(self):
        pass
    ...

  类的本质可以看做是一个存放数据与功能的字典,但是在类里面可以定义变量,可以定义函数,这无疑提升了代码体的“整合”程度。

# 定义一个类:化妆包
class 化妆包:
    x = "粉底"
    y = "腮红"
    x = "眼影"

    def 美妆蛋():
        print("开始上底妆")

    def 化妆刷():
        print("开始打腮红")

    def 眼影刷():
        print("开始画眼妆")

print(化妆包.__dict__)
# 可以得到一个字典,里面包含了所有的功能与方法
# {'__weakref__': <attribute '__weakref__' of '化妆包' objects>, '化妆刷': <function 化妆包.化妆刷 at 0x01976E40>, '__module__': '__main__', 'x': '眼影', '__doc__': None, '眼影刷': <function 化妆包.眼影刷 at 0x01976ED0>, '美妆蛋': <function 化妆包.美妆蛋 at 0x01976D68>, '__dict__': <attribute '__dict__' of '化妆包' objects>, 'y': '腮红'}
View Code

  因为类的实质就是一个字典,我们可以通过:类名.__dict__["变量名"]方法调用字典中的方法,以上为了演示效果,才使用了中文作为变量名、函数名和类名,这样不可取,希望大家不要模仿,后续将会按照规范为大家演示

# 定义一个学生类
class Student:
    school = "北京大学"
    name = "zhangdada"

    # 打印学生信息
    def show_info():
        print("学生信息")

# 通过字典调用变量
print(Student.__dict__["school"])
print(Student.__dict__["name"])

# 通过字典调用函数
Student.show_info()
View Code

  每次都要使用__dict__方法未免有点繁琐,于是python也提供了一个简洁的调用方法(真为懒人考虑):类.属性;没错只需要一个.就可以解决,后面的属性就是我们在类中定义的变量或者函数

# 调用高级用法
class Student:
    school = "北京大学"
    name = "zhangdada"

    # 打印学生信息
    def show_info():
        print("学生信息")

# 通过.调用变量
print(Student.school)
print(Student.name)

# 通过.调用函数
Student.show_info()
View Code

 

讲到这里,可能有的小伙伴已经开始晕了,啥是类?啥是对象?一个程序会有很多对象,但是某一类对象可能存在一些共有的数据或者功能,我们每创建一个对象就要写一遍这些共有的相同代码,就会使得代码冗余,那为什么不把这些共同的数据与功能放在一起,那么每次创建对象时,只需要拿来共有的数据与功能,加上自己的特性数据与功能,一个对象就诞生了,并且没有冗余代码。

我们上面说到,类实质就是一个字典,存放共有数据与功能的字典,通过类可以生成一系列相似但是又有自己特性的对象。例如有一个类是动物,存有长毛,是动物的共有特性,那么加上“汪汪汪”叫就是对象狗,加上“喵喵喵”叫就是对象猫。

 

 

 

 

 

 2、类的定义与调用

  类的定义我们上面易筋经介绍了,需要补充的是,类中定义的方法都叫做属性,类的属性分为变量属性和函数属性,顾名思义,代表了类中定义的变量和函数,其实类中可以有任何类型的代码,但是我们常用的就是这两个属性,可以通过上述的__dict__方法查看类中的全部属性

  • 如何使用类创造对象呢?

  我们只要调用类就能产生一个对象,也叫一个实例

# 类的调用
class Student:
    school = "北京大学"
    name = "zhangdada"

    # 打印学生信息
    def show_info():
        print("学生信息")


# 生成对象
stu1 = Student()
stu2 = Student()

可以看到,stu1、stu2就是通过调用产生的对象,这个对象可以访问到类中的所有数据与方法,面向对象编程操作的就是这个对象,但是我们发现一个问题,这样创建的对象好像是一样的,我们打印一下两个对象对应的字典

# 生成对象
stu1 = Student()
stu2 = Student()

print(stu1.__dict__)
print(stu2.__dict__)

#结果
{}
{}

果然是一样的但是我们之前说过,对象是共有部分加自有特性,这就需要用到__init__属性

# 类的调用
class Student:

    school = "北京大学"
    name = "zhangdada"

    # 初始化对象,赋予对象自有的特性
    def __init__(self,name,age,gender):
        self.name = name       # stu1.__dict__["name"] = name
        self.age = age         # stu1.__dict__["age"] = age
        self.gender = gender   # stu1.__dict__["gender"] = gender

    # 打印学生信息
    def show_info():
        print("学生信息")

# 生成对象
stu1 = Student("zhangdada",18,"male")

 

__init__属性其实就是在为对象设置初始化的特性数据,上述事例中,以stu1为例,展示了在类中加入__init__(self,name,age,gender)方法后,只需要调用对象时传入参数name、age、gender,生成了包含name、age、gender的对象stu1,使用相同方法,可以产生更多对象。

在调用类生成对象时,发生了三件事:

  • 会创建空对象(使用__new__方法创建新对象)
  • 创建对象后,会触发类中的__init__方法,在对象中添加方法下面的属性,注意:__init__方法不能有返回值
  • 返回一个对象并赋值给变量名

下图反映了对象与类之间的关系

 

对象查找属性的顺序:现在类自己的__dict__中寻找——>然后去类__dict__中寻找

 

 

类的属性查找

  • 首先类中的变量是类的数据属性,可以通过类名直接调用,并且无论在何处调用,指向的内存地址都是一样的
# 类的调用
class Student:

    school = "北京大学"
    name = "zhangdada"

    # 初始化对象,赋予对象自有的特性
    def __init__(self,name,age,gender):
        self.name = name       # stu1.__dict__["name"] = name
        self.age = age         # stu1.__dict__["age"] = age
        self.gender = gender   # stu1.__dict__["gender"] = gender

    # 打印学生信息
    def show_info():
        print("学生信息")

# 生成对象
stu1 = Student("zhangdada",18,"male")
stu2 = Student("hhh",20,"female")

# 调用数据属性
print(id(Student.school))   # 29441344
print(id(stu1.school))      # 29441344
print(id(stu2.school))      # 29441344
View Code
  • 其次,类中定义的函数属性,可以通过类名直接调用,这与调用函数无异,需要几个参数就传入几个参数
# 类的调用
class Student:

    school = "北京大学"
    name = "zhangdada"

    # 初始化对象,赋予对象自有的特性
    def __init__(self,name,age,gender):
        self.name = name       # stu1.__dict__["name"] = name
        self.age = age         # stu1.__dict__["age"] = age
        self.gender = gender   # stu1.__dict__["gender"] = gender

    # 打印学生信息
    def show_info(self):
        print("%s" % self.name)

# 生成对象
stu1 = Student("zhangdada",18,"male")
stu2 = Student("hhh",20,"female")

# 通过类名调用数据属性
Student.show_info(stu1)  # zhangdada
View Code
  • 绑定方法:我们在类中定义的函数属性,通常是为了给对象使用,在使用对象调用类中的函数属性时,会使用一种绑定方法,即在对象调用时,就将对象自身作为第一个参数传入函数属性中,上文没有讲到的self参数,代表的就是传入对象,使用绑定方法时,会自动传入
# 类的调用
class Student:

    school = "北京大学"
    name = "zhangdada"

    # 初始化对象,赋予对象自有的特性
    def __init__(self,name,age,gender):
        self.name = name       # stu1.__dict__["name"] = name
        self.age = age         # stu1.__dict__["age"] = age
        self.gender = gender   # stu1.__dict__["gender"] = gender

    # 打印学生信息
    def show_info(self):
        print("%s" % self.name)

# 生成对象
stu1 = Student("zhangdada",18,"male")
stu2 = Student("hhh",20,"female")

# 通过类名调用数据属性
Student.show_info(stu1)  # zhangdada

# 绑定方法
stu1.show_info()   # 等同于Student.show_info(stu1) 
stu2.show_info()   # 等同于Student.show_info(stu2) 

# 返回结果为:
# zhangdada
# hhh
View Code

 

绑定方法与非绑定方法详解

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

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

绑定给对象

绑定给类

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

 

绑定给对象

# 绑定给对象
class Mysql:

    def __init__(self,iq,sport):
        self.iq = iq
        self.sport = sport

    def info(self):
        print("%s %s" % (self.iq,self.sport))

user1 = Mysql("1.2.3.2",6625)
user1.info()
View Code

绑定给类

ID = "208.1.1.1"
Port = 3340

# 绑定给类,
class Mysql:

    def __init__(self,iq,sport):
        self.iq = iq
        self.sport = sport


    def info(self):
        print("%s %s" % (self.iq,self.sport))

    @classmethod               # 表示将类自己作为第一个参数传入函数,在类中快速生成对象
    def from_conf(cls):
        return cls(ID,Port)

obj  = Mysql.from_conf()
obj.info()                     # 208.1.1.1 3340
View Code

非绑定方法

ID = "208.1.1.1"
Port = 3340

# 绑定给类,
class Mysql:

    def __init__(self,iq,sport):
        self.id = self.create_id()
        self.iq = iq
        self.sport = sport


    def info(self):
        print("%s %s" % (self.iq,self.sport))

    @classmethod               
    def from_conf(cls):
        return cls(ID,Port)

    @staticmethod                 # 不会再讲对象当做第一个参数传入属性,此时可以看走一个函数
    def create_id():
        import uuid
        return uuid.uuid4()
View Code

 

发表评论

0/200
69 点赞
0 评论
收藏
为你推荐 换一批