首页 > 编程语言 >Python系列(8)- Python 类和对象、模块和包

Python系列(8)- Python 类和对象、模块和包

时间:2024-08-23 22:38:59浏览次数:7  
标签:__ count 系列 name Python self Person 模块 display

 

1. 类和对象

    Python 语言在设计之初,就定位为一门面向对象的编程语言,"Python 中一切皆对象" 就是对 Python 这门编程语言的完美诠释。

    类和对象是 Python 的重要特征,相比其它面向对象语言,Python 很容易就可以创建出一个类和对象。同时,Python 也支持面向对象的三大特征:封装、继承和多态。

    1) 面向对象

        面向对象编程(Object-oriented Programming,简称 OOP),是一种代码封装的方法。
        
        函数封装是一种将程序段或功能打包成可重用的代码块的过程。函数是一种面向过程的编程方法,它将一段可以执行特定任务的代码封装起来,形成一个独立的单元。

        类封装是面向对象编程的核心概念之一。类是一种用户定义的应用数据类型,它包含了属性(变量)和方法(函数)。类封装将数据和操作封装在一起,形成一个有机的整体。类提供了更高的抽象层次,可以定义对象的行为和状态。
        
        类封装更适合于复杂系统的开发,而函数封装则适用于简单的功能实现。

        面向对象相关术语:

            (1) 类(Class): 用来描述具有相同的属性 (变量)和方法(函数)的对象的集合;
            (2) 对象:对象是类的实例化,类是一个模板,对象是根据这个模板创建的具体实例;
            (3) 类属性(或称类变量): 在类体中方法(函数)之外的变量,它是类的所有实例化对象共享的变量;
            (4) 实例属性(或称实例变量):在类体中方法(函数)之内,以 "self.变量名=值" 的方式定义的变量;
            (5) 局部变量:在类体中方法(函数)之内,以 "变量名=值" 的方式定义的变量;
            (6) 方法:;
            (7) 继承:即一个派生类(derived class)继承基类(base class)的属性和方法。继承也允许把一个派生类的对象作为一个基类对象对待;
            (8) 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写;
            (9) 多态:;

            注:属性‌和变量是两个不同的概念,变量是面向过程编程、面向对象编程中都会用到的概念,属性则是面向对象编程中的一个概念,通常在类中一个属性对应一个变量,并通过 getter 和 setter 方法进行读写。即在面向对象编程时,定义/读写属性,需要比定义/读写变量采用更严谨的规范要求。
                方法和函数也是两个不同的概念,函数是面向过程编程、面向对象编程中都会用到的概念,方法则是面向对象编程中的一个概念,通常在类中一个方法对应一个函数。

    2) 类的定义和实例化

        Python 定义类使用 class 关键字,语法格式如下:

            class 类名:
                [类属性 = 值]

                def __init__(self, [参数列表]):
                    [self.实例属性 = 参数值]

                def 方法(self, [参数列表]):
                    [self.实例属性 = 参数值]
                    [局部变量 = 参数值]
                
            名词解释:

                (1) 类名:一个符合 Python 语法的标识符,类名要能够体现出该类的特征;
                (2) [类属性 = 值]: 是可选项,表示定义一个类属性,并赋值;
                (3) __init__(self, [参数列表]): __init__ (双下划线开头/结尾)是类的构造方法,创建类的对象时,会自动调用这个方法;self 表示类实例化的对象本身;[参数列表] 是可选项,和函数参数列表一样,多个参数之间用逗号分隔;
                (4) [self.实例属性 = 参数值]:是可选项,表示定义一个实例属性,并赋值;
                (5) 方法(self, [参数列表]): 方法是类的成员函数;self 表示类实例化的对象本身;[参数列表] 是可选项,和函数参数列表一样,多个参数之间用逗号分隔;

                注:[] 括表示非必选项。

        类的实例化(即创建对象),语法格式如下:

            变量 = 类名([参数列表])

            名词解释:

                (1) 类名: 就是定义类时的类名;
                (2) [参数列表]: 和函数参数列表一样,多个参数之间用逗号分隔;
                (3) 变量: 类实例化的对象。
        
        示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            class Dog:
                def display(self):
                    print('This is a dog')

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

                def display(self):
                    print('name:', self.name)

            if __name__ == "__main__":

                dog = Dog()
                dog.display()

                person = Person('Python')
                person.display()

           
        输出结果如下:

            This is a dog
            name: Python

        注:Dog 类没有 __init__() 构造方法,Python 也会自动给 Dog 类添加一个仅包含 self 参数的构造方法,这种构造方法被称为类的默认构造方法。

    3) 类中的属性

        根据变量定义的位置不同,以及定义的方式不同,类中的属性可细分为:类属性、实例属性、局部变量、内置属性。

        上文讲到,属性是面向对象编程中的一个概念,通常在类中一个属性对应一个变量。局部变量是类中方法内的变量,根据面向对象编程的概念,我们也可以把局部变量称为局部属性。

        但是,局部变量和类的属性在定义和使用上有明显的区别,为了不把问题复杂化,我们这里就不使用局部属性这个概念。
        
        (1) 类属性

            类属性或称类变量,在类体中方法(函数)之外的变量,它是类的所有实例化对象共享的变量。类变量既可以使用 '类名.变量名' 方式调用,也可以使用 '对象.变量名' 方式调用(不推荐这种方式,见下文)。

            示例:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                class Dog:
                    def display(self):
                        print('This is a dog')

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

                    def display(self):
                        print('name:', self.name)

                if __name__ == "__main__":

                    dog = Dog()
                    Dog.count = 10      # 动态为 Dog 类添加类变量 count
                    print('dog.count:', dog.count)

                    person1 = Person('Python')
                    person2 = Person('Java')
                    print('Person.count:', Person.count)

                    Person.count = 1
                    print('Person.count = 1')
                    print('Person.count:', Person.count, ', person1.count:', person1.count, ', person2.count:', person2.count)

                    person1.count = 3   # 这不是给 Person 的类变量 count 赋值,而是给对象 person1 定义新的实例变量 count
                    print('person1.count = 3')
                    print('Person.count:', Person.count, ', person1.count:', person1.count, ', person2.count:', person2.count)

                    Person.count = 5
                    print('Person.count = 5')
                    print('Person.count:', Person.count, ', person1.count:', person1.count, ', person2.count:', person2.count)


            输出结果如下:

                dog.count: 10
                Person.count: 0
                Person.count = 1
                Person.count: 1 , person1.count: 1 , person2.count: 1
                person1.count = 3
                Person.count: 1 , person1.count: 3 , person2.count: 1
                Person.count = 5
                Person.count: 5 , person1.count: 3 , person2.count: 5


            注:Python 的类变量,在默认情况下可以直接读写,尽量使用 '类名.变量名' 方式调用类变量。使用 '对象.变量名' 方式调用类变量,可能会导致给对象添加同名的实例变量的误操作。实例变量和类变量可以同名,但这种情况下,对象无法调用同名的类变量,它会首选实例变量。

        (2) 实例属性
        
            实例属性或称实例变量,在类体中方法(函数)之内,以 "self.变量名=值" 的方式定义的变量。实例变量只能使用 '对象.变量名' 方式调用,无法使用 '类名.变量名' 方式调用。

            示例:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

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

                    def display(self):
                        print('name:', self.name)

                if __name__ == "__main__":

                    person1 = Person('Python')
                    person2 = Person('Java')

                    print('Person.name:', Person.name, ', person1.name:', person1.name, ', person2.name:', person2.name)

                    Person.name = 'Person 2'
                    person1.name = 'Python 2'
                    person2.name = 'Java 2'
                    print('Person.name:', Person.name, ', person1.name:', person1.name, ', person2.name:', person2.name)

                    person1.age = 20
                    print('person1.age:', person1.age)
                    if hasattr(Person, 'age'):
                        print('Person.age:', Person.age)
                    else:
                        print('age not in Person')
                    if hasattr(person2, 'age'):
                        print('person2.age:', person2.age)
                    else:
                        print('age not in person2')


            输出结果如下:

                Person.name: Person , person1.name: Python , person2.name: Java
                Person.name: Person 2 , person1.name: Python 2 , person2.name: Java 2
                person1.age: 20
                age not in Person
                age not in person2

            注:给对象添加实例变量,或修改对象的实例变量的值,不会影响类的其它实例化对象,也不会影响同名的类变量。hasattr() 函数用来判断属性或方法是否存在。

        (3) 局部变量
        
            在类体中方法(函数)之内,以 "变量名=值" 的方式定义的变量。

            示例:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

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

                    def display(self):
                        age = 20
                        print('name:', self.name, ', age:', age)

                if __name__ == "__main__":

                    person = Person('Local')

                    if hasattr(person, 'age'):
                        print('before: person.age:', person.age)
                    else:
                        print('before: age not in person')
                    person.display()
                    if hasattr(person, 'age'):
                        print('after: person.age:', person.age)
                    else:
                        print('after: age not in person')


            输出结果如下:

                before: age not in person
                name: Local , age: 20
                after: age not in person

            注:局部变量 age 的作用域就是在 disply() 之内的范围,方法执行完成后,age 即被销毁

        (4) 内置属性
        
            内置属性或称内置变量,是指在 Python 类中用双下划线开头/结尾的特殊属性,如 __name__、__doc__ 等。
            
            这些属性通常用于定义类的元数据,控制类的行为,或者在类的不同部分之间交互。使用 dir() 函数看类或对象的内置属性,运行如下代码:

                print(dir(Person))  # 查看类
                print(dir(person))  # 查看对象

            内置方法也是用双下划线开头/结尾的特殊方法,如 __call__, __del__ 等,也可以使用同样方式查看。

    4) 类中的方法

        类中的方法可分为实例方法、类方法、静态方法、。

        (1) 实例方法

            在类中定义的方法默认都是实例方法,它至少包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。

            示例:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

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

                    def display(self, str):
                        print(self.name, str)

                if __name__ == "__main__":

                    person = Person('Hello')
                    person.display('Java')

                    Person.display(person, 'Python')


            输出结果如下:

                Hello Java
                Hello Python

                注:可以使用实例对象调用,第一个参数无需传入对象引用;也可以使用类调用,第一个参数要传入对象引用。

        (2) 类方法
        
            类方法需要使用 @classmethod 修饰,它至少包含一个 cls 参数,用于绑定调用此方法的类本身(Python 会自动完成绑定)。类方法推荐使用类名直接调用,也可以使用实例对象来调用(不推荐使用这种方式)。

            示例:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

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

                    @classmethod
                    def display(cls, str):
                        print(cls.name, str)

                if __name__ == "__main__":

                    Person.display('Python')

                    person = Person('Hello')
                    person.display('Java')


            输出结果如下:

                class Python
                class Java
    
        (3) 静态方法

            静态方法需要使用 @staticmethod 修饰,无需添加 self 参数或 cls  参数。

            示例:

               #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                class Person:

                    @staticmethod
                    def display(str):
                        print(str)

                if __name__ == "__main__":

                    Person.display('Python')

                    person = Person()
                    person.display('Java')


            输出结果如下:

                Python
                Java

    5) 类的继承

        Python 中,实现继承的类称为子类,被继承的类称为父类(也可称为基类、超类)。     

        类继承只需在定义类的时候,将父类作为参数传给子类,语法格式如下:

            class 类名(父类1, 父类2, ...):
                # 类体

            注:类定义时没有传父类参数,则默认继承 object 类,object 类是 Python 中所有类的父类。

        示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            class Person:
                def display(self, str):
                    print(str)

            class Man(Person):
                pass

            if __name__ == "__main__":

                man = Man()
                man.display('Python')


        输出结果如下:

            Python

    6) 方法重写和多态

        方法重写就是在子类中添加与父类同名的方法,两个同名方法可以拥有不同数量的参数。

         示例:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

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

                def display(self, str):
                    print(self.prefix, ':', str)

            class Man(Person):
                def __init__(self, prefix):
                    super().__init__(prefix)

                def display(self, str):
                    print(self.prefix, ':', str)

            def display(obj, str):
                obj.display(str)

            if __name__ == "__main__":

                man = Man('Man')
                man.display('Python')

                # 通过父类调用到父类 display() 函数
                Person.display(man, 'Java')

                # 多态
                person = Person('Person')
                display(person, 'polymorphic')
                display(man, 'polymorphic')


        输出结果如下:

            Man : Python
            Man : Java
            Person : polymorphic
            Man : polymorphic

        注:通过子类的对象 man 无法访问被重写的父类 display() 函数,参考上文的 '实例方法' 部分,可以通过父类 Person 调用到父类 display() 函数。

            子类 Man 的 __init__() 初始化时,把 prefix 值通过 super() 方式传给了父类 Person。

            全局函数 display(obj, str) 中,obj.display() 表现出了多态。如果 obj 是 Person 类型,就使用 Person 的 display(); 如果 obj 是 Man 类型,就是用 Man 的 display().

 

2. 模块和包

    Python 模块 (Module),是一个 Python 文件 (*.py), 可以包含多个类、函数、变量。

    函数是对 Python 代码的封装,类是对方法和属性的封装,模块是比函数、类更大范围的封装。

    1) import 语句

        import 语句用于导入 Python 标准库的模块、第三方库的模块或自定义模块,语法格式如下:

            import module1, module2 as mod2, ...

        解释说明:

            (1) import 语句可以导入一个模块,也可以同时导入多个模块,as 语句是给模块取别名;
            (2) 多行 import 语句导入同名模块,该同名模块只会被导入一次;
            (3) import 会导入模块中的所有成员(包括变量、函数、类等);

    2) from ... import 语句

        from ... import 语句用于导入指定模块内的类、函数或变量,语法格式如下:

            from module import name1, name2 as n2, ...

        解释说明:

            (1) 该语句可以导入一个模块的单个成员,也可以同时导入多个成员;
            (2) from ... import * 可以导入模块中所有成员,不推荐使用这种方式。

    3) 自定义模块

        示例,创建一个 Python 模块文件 mod.py, 代码如下:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            _var1 = 5
            __var2 = 9
            data = 'Test data'

            message = 'It is custom module'

            def display(str):
                print(str)

            class Format:
                def display(self, str):
                    print(str)

            __all__ = ['message', 'display', 'Format']


            注:单下划线 “_” 或者双下划线 “__” )开头的变量 _var1、__var2, 仅在 from ... import * 导入方式时会被忽略而不导入。

                仅在 from ... import * 导入方式时,如果由 __all__ 变量,只能导入 __all__ 变量指定的成员。

        创建一个使用 mod 模块的 Python 文件 run_mod.py,和 mod.py 在同一级目录下, 代码如下:

            #!/usr/bin/python3
            # -*- coding: UTF-8 -*-

            import mod
            from mod import message, display, Format


            # import
            mod.display(mod.message)

            format = mod.Format()
            format.display('Format: ' + mod.message)

            # from ... import
            display('from ... import -> ' + message)

            format2 = Format()
            format.display('from ... import -> Format: ' + message)


        输出结果如下:

            It is custom module
            Format: It is custom module
            from ... import -> It is custom module
            from ... import -> Format: It is custom Module

    4) 包 (package)

        Python 包(package)就是一个存放多个 Python 模块的文件夹,该文件夹下必须存在一个名为 '__init__.py' (前后都是双下划线) 的文件,__init__.py 文件可以是个空文件。

        (1) 创建包

            创建一个 demo_package 目录,在 demo_package 目录下创建 3 个 Python 文件 __init__.py、mod1.py、mod2.py。

            文件 __init__.py, 内容如下:

                __all__ = ['mod1']
            
            文件 mod1.py, 内容如下:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                message = 'It is custom module'

                def display(str):
                    print(str)


            文件 mod2.py, 内容如下:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                def display(str):
                    print(str)


            demo_package 包的文件结构如下:

                demo_package
                    |-- __init__.py
                    |-- mod1.py
                    |-- mod2.py

        (2) 导入包

            创建一个 Python 文件 test.py 和 demo_package 在同一级目录,test.py 内容如下:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                import demo_package as demoPackage  # 包的本质就是模块,可以用 import 导入
                import demo_package.mod1 as demoMod1
                import demo_package.mod2 as demoMod2

                print(demoPackage.__all__)  # 此时 demoPackage 对应 __init__.py 文件

                demoMod1.display('1 -> ' + demoMod1.message)
                demoMod2.display('2 -> ' + demoMod1.message)


            输出结果如下:

                ['mod1']
                1 -> It is custom module
                2 -> It is custom module

            修改 test.py 内容如下:

                #!/usr/bin/python3
                # -*- coding: UTF-8 -*-

                import demo_package as demoPackage  # 包的本质就是模块,可以用 import 导入
                from demo_package import *

                print(demoPackage.__all__)  # 此时 demoPackage 对应 __init__.py 文件

                mod1.display('1 -> ' + mod1.message)
                mod2.display('2 -> ' + mod2.message)


            输出结果如下:

                ['mod1']
                1 -> It is custom module
                Traceback (most recent call last):
                File "d:/pythonDemo/test.py", line 16, in <module>
                    mod2.display('2 -> ' + mod2.message)
                NameError: name 'mod2' is not defined

            注:__init__.py 文件里的 __all__ 变量,仅在 from demo_package import * 导入方式时,只允许 mod1 模块被访问,


标签:__,count,系列,name,Python,self,Person,模块,display
From: https://www.cnblogs.com/tkuang/p/18377187

相关文章

  • Python3 基础语法
    编码默认情况下,Python3源码文件以 UTF-8 编码,所有字符串都是unicode字符串。当然你也可以为源码文件指定不同的编码:#-*-coding:cp-1252-*-上述定义允许在源文件中使用Windows-1252字符集中的字符编码,对应适合语言为保加利亚语、白俄罗斯语、马其顿语、俄语、......
  • PDH鉴频信号_python代码
    PDH鉴频信号PHD原理与代码PHD原理PHD鉴频信号幅度和频率的关系图代码PHD原理与代码PHD原理PDH技术中以腔的基模频率为参考,使用腔的反射信号来制备误差信号。具体地,考虑一个幅度为......
  • Python Lambda 表达式详解
    PythonLambda表达式详解1.引言在Python中,lambda表达式是一种创建小型匿名函数的方法。这种函数不需要使用def关键字来定义,通常用于编写简短的函数或作为其他函数的参数。lambda函数可以接受任意数量的参数,但只能有一个表达式,该表达式的结果就是函数的返回值。2.Lambd......
  • Python时间戳转换为标准时间
    前置知识北京时间是中华人民共和国全境采用的国家标准时间(UTC(NTSC)或CST),是首都北京所在的东八时区的区时。北京时间比格林威治时间(GreenwichMeanTime简称GMT)早8小时。协调世界时,又称世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称U......
  • python-flask计算机毕业设计中小学精品课程网络资源系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,教育领域正经历着前所未有的变革。互联网技术的普及,使得优质教育资源的共享成为可能,为教育公平与质量提升提供了强......
  • python-flask计算机毕业设计校园疫情检测信息管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着全球疫情的持续影响,校园作为人员密集、流动性大的特殊场所,其疫情防控工作显得尤为重要。传统的手工记录、纸质申报等管理方式已难以满......
  • YOLOv8改进系列,YOLOv8添加BiFormer注意力机制,助力小目标检测能力
    原论文摘要作为视觉Transformer的核心构建模块,注意力机制是捕捉长距离依赖关系的强大工具。然而,这种能力伴随着高昂的代价:由于需要计算所有空间位置之间的成对标记交互,导致巨大的计算负担和高内存占用。一系列工作试图通过引入手工设计的与内容无关的稀疏性来缓解这一问......
  • YOLOv8改进系列,YOLOv8添加MLCA注意力机制(混合局部信道注意)
    原论文摘要注意力机制是计算机视觉中最广泛使用的组件之一,能够帮助神经网络突出重要元素并抑制不相关的部分。然而,大多数通道注意力机制只包含通道特征信息,忽略了空间特征信息,导致模型的表示效果较差或目标检测性能不佳,并且空间注意力模块往往复杂且代价高昂。为了在性能......
  • UE Shader 解读系列(一) ShadingCommon.ush
    UEShader解读系列(一)ShadingCommon.ush本文基于UE5.3.2是对ChatGPT给的解释进行的copy,不一定正确ShadingCommon.ush包含了UE的shader编写相关的基础定义和工具函数1.宏定义与条件编译#ifndefSHADING_PATH_MOBILE#defineSHADING_PATH_MOBILE0#endif#ifnd......
  • 【python2-2】数据类型
    整型intinput()里面输出的都是字符串类型的,要转换成int类型在进行加减乘除num=input('请输入一个数字:')print(type(num))num=int(num)+10print(num)浮点数产生误差:采用round四舍五入:n1=0.1n2=0.2n3=round(n1+n2,2)print(n3)取整操作:向上取整......