欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python(二十三)类和对象

程序员文章站 2024-03-17 16:22:40
...

一、基本概念

Python目的:力求提供简单够用的语法功能,所以你会看到其面向对象比较简单,不像其他面向对象语言(Java等)提供了大量繁杂的面向对象的特征!

了解面向对象的程序设计语言的两个重要概念!

(0)辨析面向对象和面向过程

面向过程 面向对象(oop:object oriented programming)
面向过程:---侧重于怎么做?
1.把完成某一个需求的 所有步骤 从头到尾 逐步实现
2.根据开发要求,将某些功能独立的代码封装成一个又一个函数
3.最后完成的代码,就是顺序的调用不同的函数
特点:
    1.注重步骤和过程,不注重职责分工
    2.如果需求复杂,代码变得非常复杂
    3.开发复杂的项目的时候,没有固定的套路,开发难度很大
面向对象:----侧重于谁来做?
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
1.在完成某一个需求前,首先确定职责--要做的事(方法)
2.根据职责确定不同的对象,在对象内部封装不同的方法(多个)
3.最后完成代码,就是顺序的让不同的对象调用不同的方法
特点:
    1.注重对象和职责,不同的对象承担不同的职责
    2.更加适合对复杂的需求变化,是专门应对复杂项目的开发,提供固定的套路
    3.需要在面向过程的基础上,再学习一些面向对象的语法

面向过程--->侧重于怎么做?
面向对象--->测中于谁来做?

小结:

(1)类的概念

把握:严谨的定义和自定义理解!

:大概就是一些具有相同属性的对象的集合的抽象描述,可以理解某种概念

:是一类具有相同特征或行为的事物的一个统称!

(2)对象的概念

对象:按照类的模版创建的一个具体的实例(体)!

明确

         创建出来的对象叫做类的实例

         创建对象的动作(过程)叫做实例化

         类与对象是个性和共性的关系

(3)类的定义

     类名:是合法的标识符即可,满足大驼峰命名规范,类名由有意义的单词连缀组成,单词首字母大写,其余小写,单词之间没有任何的分割符号

Python(二十三)类和对象

说明:懒的画图,随手copy了一张!

备注:python3.x系列的版本会自动的继承超类object,即不需要手动的继承!

# ":"作为类体的开始,统一缩进的内容作为类体!
class LibraySystem(object):
    # pass语句作为占位符号
    pass

#说明:空类没有太大的意义!

类的作用:定义变量、创建对象、派生子类!

(3)类的成员

核心:变量和方法

修饰符扩展:类变量、实例变量、私有方法、类方法、实例方法、静态方法、类变量、私有变量、实例变量

常见的修饰符:@关键字、以双下划线开头、以双下划线结尾、以双下划线开头和结尾(python内置)的

说明:具体的表现形式后面讲解!

(4)对象的创建和方法的调用

class Person:
    '类定义说明文档,放在类声明之后,类体之前'
    # python的内置方法-->构造方法
    # 说明:如果没有自定义构造方法来初始化对象,则默认是只包含一个self参数的__init__函数
    # self参数:被绑定到构造方法的初始化"对象上"!
    def __init__(self, name):
        self.name = name
        print('%s被创建' %(self.name))

    # 没有被特殊修饰的就是实例方法
    def say(self, linux):
        print('hello' + linux)

# 创建对象返回的是一个引用
person=Person('老李')
# 调用方法-->对象.方法(参数)
person.say('linux')
# 访问变量-->对象.变量名
print(person.name)

  注意:Python的没有方法重载,即相同的函数名,不同的函数列表的函数!

  方法中self参数理解:哪一个对象调用的方法,self就是哪一个对象的引用,self就是调用者本身!
        1)在封装的方法内部,self就表示当前调用方法对象自己
        2)在调用方法的时候,程序员不需要传递self参赛(定义的时候,第一个参数默认是self,自动绑定

谁调用(发起),self就是谁(那个对象)!

明确:只是一个形式参数,可以随意命名,只是约定俗成(规范),具有更好的可读性而已!

(4)Python的动态语言特性和内置方法的使用

    4.1)动态特性

            变量:对象动态的增加删除变量

class Person:
    def __init__(self, name):
        self.name = name

p = Person('wzj')
#(1)增加属性
p.height = 175
print(p.height)
# (2)删除属性
del p.height
print(p.height)

# 说明:只是针对这个对象而言的!

            方法动态的添加方法

# (0)定义一个类
class Person:

    def __init__(self, name):
        self.name = name

# (1)自定义一个函数
def define(self):
    print('为对象动态的增加一个方法', self)

# (2)动态增加方法
p = Person('猫腻')
# 说明:foo只是一个变量,存储的是函数的引用!
p.foo = define
# 调用方法
p.foo(p)

# 说明:dir可以看到一个对象或者类的成员
print(dir(p))

说明:这个案例有助于理解类体中方法self参数的含义,这个是类体外针对象的!

注意:动态的增加方法,python不会自动将调用者绑定到第一个参数中,所以需要自己指定!

需求:借助其它模块,后续

    4.2)内置方法

特点:以__开头和结尾的

class Person:

    def __init__(self, name):
        self.name = name

    # 强调:返回必须是一个字符串
    # 说明:重写了object基类的方法,不希望打印对象的地址值!
    def __str__(self):
        return "不用地址数值,而是自定义%s" % (self.name)

    # 对象销毁前做的扫尾工作,把对象从内存中销毁(垃圾回收)
    def __del__(self):
        print('%s 走了' % (self.name))

print(Person('老李'))
print(Person('老吴'))

关于自动绑定self的方法再强调几点

说明:根据第一个参数出现的位置不同,第一个参数绑定的对象略有不同

       构造方法中:表示引用构造方法正在初始化的对象

       实例方法中:引用调用该方法对象

self的作用:引用当前方法的调用者(对象)!

了解:self表示所代表的对象是不确定的,但是类型是确定的,只有在方法被调用的那一刻,它所代表的对象才确定!

self的应用:对象的一个方法依赖于另一个方法-

class Person:

    def __init__(self, name):
        self.name = name
    def run(self):
        print('跑得快')
    def drink(self):
        # 错误的方法调用(省略了self)
        # run()
        # 正确的方法调用,区别于Java!
        self.run()

########说明:上述所讲的都是##########

(5)方法细讲

        5.1)实例方法:类体中定义的一般方法

说明:由于与实例挂钩,所以与对象有直接的联系,又因为对象是由类创建的,所以实例方法有两种调用方式

class Person:
    def __int__(self):
        print('hello')

    def run(self):
        print(self,'正在跑')
# (1)实例调用方法
Person().run()

# (2)类调用实例方法
Person.run(Person())

# 疑惑:二者的内存空间竟然一致,会不会是Python版本的问题

区别类调用实例方法,Python不会自动为第一个参数绑定调用者,而对象调用实例方法会

注意:不管是哪种方式调用实例方法都会进行对象的初始化!

        5.2)类方法和静态方法

class Person:
    @classmethod
    # 说明:cls会自动绑定到类本身!
    def run(cls):
        print('类方法',cls)

    @staticmethod
    # 说明:静态方法如果想绑定参数,需要手动绑定!
    def static(p):
        print('静态方法',p)

# (1)调用类方法-->会自动绑定到第一个参数
# 方式1
Person.run()
# 方式2
Person().run()

# (2)调用静态方法-->不会自动绑定到第一个参数
# 方式1
Person.static(Person())
# 方式2
Person().static(Person())

说明:虽然可以通过类或者对象来调用静态和类方法,但是推荐使用来调用

区别:静态方法不管哪种方式的调用都不会自动绑定都不会调用构造方法

练习

class Toy(object):
    # 类属性
    count = 0

    def __init__(self, name):
        self.nama = name
        # 说明:调用类方法时回创建对象
        # self.count +=1
        Toy.count += 1

    @classmethod
    def show_toy_count(cls):
        # 类方法可以调用类属性
        print('玩具的数量 %d' % (cls.count))

# 测试-->创建玩具对象
toy1 = Toy('乐高')
toy2 = Toy('小米')

# 调用类方法-->注意调用方式!
Toy.show_toy_count()

应用场景工厂模式

由静态方法引出的函数装饰器

        5.3)私有方法

备注:私有方法在讲解Python面向对象的三大特性的风转时讲解!

明确一点:不是绝对私有的(与Java比较)

理解:类的命名空间和全局空间

函数和类的方法区别:看是在类的命名空间还是全局空间中!

(6)变量的细讲

        6.1)类变量和实例变量

需求:类变量和实例变量的读取和修改

class Person:
    # (1)定义一个实例变量
    name = '老李'
    age = 18

    # (2)定义实例方法
    def fun(self, name):
        # 说明1:下面赋值语句(name)不是对类变量的赋值,而是定义新的实例变量
        self.name = name
        # 说明2:由于在对象中找不到此变量,所以会在类变量中寻找age!
        print("%s的年龄也是%d" % (self.name, self.age))


# (1)类变量
# 读取方式:类名调用
print(Person.name)
print(Person.age)
# 修改方式
Person.name = 'kangkang'
print(Person.name)

# (2)实例变量
# 读取:实例变量(第一次调用该方法的时候)
p = Person()
p.fun('wzj')
# 修改:由于对象中已经有此实例变量,此时就是修改
p.name = '老吴'
print(p.name)

# 说明:由于Python是动态语言,赋值语句往往意味着定义新的实例变量!

类变量:在类命名空间中定义的变量就是类变量!

        6.2)私有变量

说明:后续讲到封装的时候再讲解