美文网首页
python3之模块和面向对象

python3之模块和面向对象

作者: rr1990 | 来源:发表于2019-05-16 20:42 被阅读0次

    一、模块介绍

    一个.py文件就是一个模块,模块中可以定义函数、类和变量。

    • 模块包括:内置模块、三方模块和自定义模块。
    • 模块的优点:
      提高代码的可维护性
      提高代码的复用性
      避免了函数名和变量名的冲突
      可以引用其他模块

    1. 引用模块

    • import语句:
    import 模块1[, 模块2..., 模块n]
    import 模块名.函数名
    import 模块名.变量名
    
    • from...import...语句
    from 模块名 import 方法1[, 方法2, ...方法n]
    从模块中导入指定的方法到当前命名空间
    from 模块名 import *
    把模块中的所有内容全部导入到当前命名空间
    
    • 导入模块指定别名
    from 模块名 import 方法1 as name
    从模块中导入方法1并指定别名为name,调用时name.XXX或name(XXX)
    
    • 引用模块的方法注意事项:
      同一模块无论被import多少次,为了防止重复引入,均只会被引入一次。
      可一次性引入多个模块,不同模块之间用逗号分隔

    2. 模块中特殊属性

    2.1. __name__属性

    模块就是一个可执行的.py文件,一个模块被另一个程序引入。
    如果不想让模块中的某些代码执行,可以用__name__属性。每个模块都有一个__name__属性。
    当前文件如果为程序的入口文件时,则__name__ == "__main__"。当__name__属性的值为"__main__"时,则表明该模块自身在执行;否则被引用其他文件。

    3. 包

    防止模块命名冲突,引入按目录来组织模块的方法,称为包package。
    引入包后,只要顶层的包与其他文件不冲突,此包下的模块就不会与其他文件发生冲突。
    每个包下必须存在一个__init__.py文件,此文件内容可为空。
    __init__.py文件的作用:避免一些滥竽充数的名字,且目录下只有存在此文件才可认为此目录为一个包。

    4. 安装第三方模块

    (1)前提:安装python时安装有pip
    查看是否安装有pip方法,命令行输入pip -V

    C:\Users\admin>pip -V
    pip 18.1 from d:\programs\python\python36\lib\site-packages\pip (python 3.6)
    

    (2)安装三方模块

    • pip install 模块名
      安装模块时有时会报错,提示升级pip版本。
    • pip install --upgrade pip:升级pip版本
    (1)安装Pillow模块:
    C:\Users\admin>pip install Pillow
    Requirement already satisfied: Pillow in d:\programs\python\python36\lib\site-packages (5.3.0)
    You are using pip version 18.1, however version 19.1.1 is available.
    You should consider upgrading via the 'python -m pip install --upgrade pip' command.
    ---报错,提示升级pip
    (2)升级pip
    遇到过升级pip后无法找到pip模块:
    File "D:\Programs\Python\Python36\Scripts\pip.exe\__main__.py", line 5, in <module>
    ModuleNotFoundError: No module named 'pip'。但实际上有pip文件。
    解决方案:
    首先执行:python -m ensurepip
    再升级pip:python -m pip install --upgrade pip
    

    (3)查看pip安装的模块

    • pip list:列出所有的模块信息
    • pip show -V 模块名 | findstr Version:window下获取某个模块的版本号
    • pip show -V 模块名 | grep Version:Linux下获取某个模块的版本号

    二、面向对象

    1. 面向过程和面向对象的介绍

    1.1. 面向过程:

    • 程序从上到下顺序执行的代码 。
    • 面向过程强调的是功能行为

    1.2. 函数式:

    • 将功能代码封装到函数中,无需重复编写,仅调用函数。

    1.3. 面向对象:

    • 把数据及对数据的操作方法放在一起,作为一个相互依赖的整体,这就是对象。
    • 把对同类对象抽象出其共性,形成类。
      类中的大多数数据,只能用本类的方法进行处理;
      类通过一个简单的外部接口与外界发生联系,对象与对象之间通过消息进行通信;
      程序流程由用户在使用中决定;
    • 面向对象是基于面向过程的。
    • 面向对象是将功能封装成对象,强调的是具备功能的对象
    • 面向对象可以将复杂的事情简单化
    • 面向对象OO(object-oriented)的三大特性:多态、封装、继承。

    2. 类

    2.1. 类的介绍

    • 类是用来描述事件的属性和行为动作。
      属性:对应类中的成员变量;
      行为:对应类中成员方法或功能;
      定义类就是定义类中的成员(成员变量和成员方法),拥有相同属性和行为的对象都可以使用此类。
      设计类包括:类名、属性、行为(方法/功能)。

    2.2. 创建类

    • 类是一种数据类型,本身并不占内存空间。用类创建实例化对象(变量),对象占内存空间。
    • 类以class 关键词开头,后接类名(类名通常是以大写开头的单词)
    • 定义有继承的类,则在类名后紧跟以括号括起来的父类名,表示该类是从此父类继承下来的。一个类可以继承多个类,类之间用逗号分隔。
      若无合适的继承类,可使用object类(object类是所有类最终都会继承的类。)---object类又称基类和超类。
    • 类中定义的函数,第一个参数永远是self,并且调用时不用传递该参数。self代表类的实例,即某个对象。(注:没有在类中定义的函数,参数中无需添加变量self)
    -----创建类的格式:
    class 类名(父类1, 父类2...): 
       属性
       行为
    
    -----访问类
    1. 使用类实例化对象
    实例化对象格式:对象名 = 类名(参数列表)
    注:类没有参数,类名后的小括号也不可省略。
    2. 访问属性
    访问属性格式:对象名.属性名
    赋新值:对象名.属性名 = 新值
    3. 访问方法
    访问方法格式:对象名.方法名(参数列表)
    
    # 创建不含继承的类
    class Student1:
        name = "zhangsan"       # 属性
    
        def getScore(self, score):      # 方法
            print("这个学生的分数是:", score)
    
    # 获取类的实例化对象
    student1 = Student1()
    # 访问属性
    getName = student1.name
    print(getName)              # zhangsan
    # 访问方法
    student1.getScore(90)       # 这个学生的分数是: 90
    
    # 创建含继承的类
    class Student2(object):
        name = "zhangsan"       # 属性
    
        def getScore(self, score):      # 方法
            print("这个学生的分数是:", score)
    
    # 获取类的实例化对象
    student2 = Student2()
    # 访问属性
    getName = student2.name
    print(getName)              # zhangsan
    # 访问方法
    student2.getScore(80)       # 这个学生的分数是: 80
    

    2.3. 构造函数

    • 构造函数__init__():即对象的初始化,使用类创建对象的时候自动调用。
    -----创建类的格式:
    class 类名(父类1, 父类2...): 
        def __init__(self, 属性1, 属性2,...):      # 属性
            self.属性1 = 属性1      
            self.属性2 = 属性2
            ...
       def 方法函数(self, 方法参数1, 方法参数2, ...)
            行为
    
    -----访问类
    1. 使用类实例化对象
    实例化对象格式:对象名 = 类名(属性参数列表)
    注:类没有参数,类名后的小括号也不可省略。
    2. 访问属性
    访问属性格式:对象名.属性名
    赋新值:对象名.属性名 = 新值
    3. 访问方法
    访问方法格式:对象名.方法名(方法参数列表)
    
    # 创建含构造函数的类
    class Student3(object):
        def __init__(self, name):
            self.name = name
    
        def getScore(self, score):
            print("这个学生的分数是:", score)
    
    # 获取类的实例化对象
    student3 = Student3("liNing")
    # 访问属性
    print(student3.name)        # liNing
    # 访问方法
    student3.getScore("70")     # 这个学生的分数是: 70
    

    2.4. self介绍

    • self代表类的实例,而非类。
      哪个对象调用方法,那么该方法中的self就代表哪个对象。
      self不是python的关键字,将对象方法中的self换成其他标识符也可以,但一般常规是用self。
    1. -----类的内部访问属性和方法-----
    访问属性格式:self.属性名
    访问方法格式:self.方法名(参数)
    获取类名:self.__class__
    2. -----类的外部访问属性和方法-----
    访问属性格式:类的实例化对象.属性名
    访问方法格式:类的实例化对象.方法(参数)
    
    """类的内部和外部分别获取属性和方法"""
    class Student4(object):
        def __init__(self, name):
            self.name = name
    
        def getScore(self, score):
            return score
    
        def getStudentInfo(self, score):
            print("姓名:%s,分数:%d" % (self.name, self.getScore(score)))       # 类的内部访问属性和方法
    
        def getClassName(self):             # 获取类名
            print(self.__class__)
    
        def createObject(self):             # 创建对象
            newObject = self.__class__("LiHong")
            print(newObject)
    
    # 获取类的实例化对象
    student4 = Student4("LiMing")
    # 类的外部访问属性
    print(student4.name)                # LiMing
    # 类的外部访问方法
    student4.getStudentInfo(80)         # 姓名:LiMing,分数:80
    student4.getClassName()             # <class '__main__.Student4'>
    student4.createObject()             # <__main__.Student4 object at 0x000000000234E240>
    

    2.5. 析构函数

    • 析构函数__del__():释放对象时自动调用,一般不需要手动添加析构函数。
      只有当对象的引用数为0时才会自动调用析构函数来回收资源。
      在函数中定义的对象,会在函数结束时自动释放,以减小内存空间的浪费。
      del 对象:手动删除对象时会调用析构函数。对象释放后不可再访问此对象。
    • 构造函数和析构函数的区别
      创建一个对象时一定会调用构造函数;
      对象结束时一定会调用析构函数。
    class Student5(object):
        def __init__(self, name):
            self.name = name
    
        def getScore(self, score):
            return score
    
        def getStudentInfo(self, score):
            print("%s的分数是%d" % (self.name, self.getScore(score)))
    
        def __del__(self):
            print("这是个析构函数")
    
    student5 = Student5("LiMing")
    print(student5.getScore(80))
    student5.getStudentInfo(80)
    # del student5                  # 删除student5对象
    # student5.getStudentInfo()     # 删除student5对象后,不可再使用此对象,否则会提示对象未被定义
    print("代码结束")
    """运行结果:
    80
    LiMing的分数是80
    代码结束
    这是个析构函数
    """
    

    2.6. 类中特殊方法__str__()__repr__()

    • __str__():在调用print打印对象时自动调用,是给用户使用的,是一个用来描述对象的方法。
    • __repr__():在python解释器中输入对象名时,调用的方法。
      注意:在没有__str__,但有__repr__时,调用print打印对象时会自动调用__repr__
      优点:当一个对象的属性值很多,并且都需要打印多次时,可将属性信息添加到此方法中,简化代码。
      __str__()__repr__()方法使用任意一种即可,一般使用__str__()
    class Student6(object):
        def __init__(self, name, sex, score):
            self.name = name
            self.sex = sex
            self.score = score
    
        def getStudentInfo(self):
            print("%s的分数是%d" % (self.name, self.score))
    
        def __str__(self):      # 这是个__str__函数
            return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)
    
        def __repr__(self):     # 这是个__repr__函数
            return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)
    
    # 获取类的实例化对象
    student6 = Student6("LiMing", "female", 80)
    # 打印对象
    print(student6)         # name=LiMing, sex=female, score=80
    

    2.7. 类中私有属性

    • 在属性前加两个下划线,则表示该属性为私有属性。在类的外部不可使用或访问私有属性,但在类的内部可以正常访问。
    • 若在类的外部直接访问私有属性,python解释器会把该私有属性名变为_类名__私有属性名(即_Person1__money),且不同的解释器将该私有属性名修改的名字可能不同,故不允许使用类直接访问私有属性。-----私有属性并不是绝对私有
    • 可通过自定义的方法修改私有属性的值和获取私有属性的值-----类的外部间接访问私有属性。
      私有属性一般会通过添加set方法和get方法来访问。
    • 在属性前后均加两个下划线,则该属性并不是私有属性,而是特殊变量,类内外部均可直接访问。
    """外部无法访问私有属性"""
    class Person1(object):
    
        def __init__(self, name, sex, money):
            self.name = name
            self.sex = sex
            self.__money = money
    
        def getInfo(self):
            print("%s拥有%d钱" % (self.name, self.__money))        # 内部可以使用私有属性__money
    
    person1 = Person1("LiMing", "female", 1000)
    # print(person1.__money)       # 报错,外部无法访问私有属性__money
    # person1.__money = 100       # 外部也可以访问此私有属性,但此私有属性名已发生改变,故不允许此用法
    
    """外部修改和获取私有属性的方法"""
    class Person2(object):
        def __init__(self, name, sex, money):
            self.name = name
            self.sex = sex
            self.__money = money
    
        def setMoney(self, money):      # 修改私有属性的值
            if money < 0:
                money = 0
            self.__money = money
    
        def getMoney(self):             # 获取私有属性的值
            return self.__money
    
    person2 = Person2("LiMing", "female", 1000)
    print(person2.getMoney())           # 1000
    person2.setMoney(200)              
    print(person2.getMoney())           # 200
    

    3. 面向对象的简单例子

    """用例:人开车
    分析:需要创建三个类,人、车、油箱
    人---类名:Person;属性:car;方法:开车、加油
    车---类名:Car;属性:油箱;方法:车跑
    油箱---类名:OilBox;属性:油
    """
    
    class OilBox(object):      
        """创建一个油箱"""
        def __init__(self, oil):
            self.oil = oil
    
    class Car(object):
        """创建一个车"""
        def __init__(self, oilBox):
            self.oilBox = oilBox      # 油箱
    
        def run(self):
            """车执行跑操作"""
            if self.oilBox.oil == 0:
                print("没有油了")
            else:
                self.oilBox.oil -= 10
                print("剩余油量", self.oilBox.oil)
    
    class Person(object):
        """创建一个人"""
        def __init__(self, car):
            self.car = car
    
        def driver(self):
            """人要开车, 车要跑"""
            self.car.run()
    
        def addOil(self, oil):
            """给车加油"""
            self.car.oilBox.oil = oil
    
    """使用面向对象实现人开车操作"""
    from Examples.Example1.person import Person
    from Examples.Example1.car import Car
    from Examples.Example1.oilBox import OilBox
    
    oilBox = OilBox(100)    # 创建一个油箱对象
    car = Car(oilBox)        # 创建一个车对象
    person = Person(car)    # 创建一个人对象
    person.driver()          # 人开车
    person.addOil(200)    # 人加油
    person.driver()
    

    三、继承

    1. 继承定义

    • 类A继承类B,则继承者(A)称为子类(派生类),被继承者(B)称为父类(基类或超类)。
      object类是所有类的父类(基类或超类)。
      子类可以直接使用父类中的属性和方法,而不用重新编写代码;
      子类可以重新定义父类中的某个属性和重写某个方法,从而覆盖父类中原有的属性和方法;
      子类可以添加新的属性和方法。
    • 继承的优点:简化代码,减小冗余;提高了代码的健壮性和安全性。
    • 继承的缺点:继承的耦合性很高(因为父类发生改变,子类也会发生改变)。
      耦合性:模块之间相互联系的紧密程度,越紧密耦合性越强;
      内聚性:一个模块内部各个元素彼此结合的紧密程度。
      耦合与内聚是描述类与类之间的关系的,耦合性越低内聚性越高,代码越好。
    • 继承分为:单继承、多继承。

    2. 单继承

    单继承即仅继承一个类。

    2.1. 子类属性的继承和重写

    • 子类中无构造函数
      子类中若无构造函数,则子类也可直接使用父类的属性。
    • 子类中构造函数的重写
      父类中存在构造函数,子类中也有构造函数,则子类的构造函数需要调用父类的构造函数。
      子类构造函数中也可添加有新的属性。
    子类中构造函数调用父类构造函数有两种方法:
    第一种:父类.__init__(self, 参数1, 参数2, ...)
    第二种:super(子类, self).__init__(参数1, 参数2, ...)
    

    2.2. 子类方法的继承和重写

    • 子类中无与父类相同的方法,则子类可以直接使用父类的方法。
    • 子类中存在与父类相同的方法,则子类的方法会覆盖父类的方法。

    2.3. 子类继承单个父类的例子

    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def eat(self, food):
            print("%s正在吃%s" % (self.name, food))
    
    """------子类使用父类的属性和方法------"""
    class Teacher1(Person):
        pass
    
    # 子类使用父类的属性
    teacher1 = Teacher1("A", 20)
    print(teacher1.name, teacher1.age)  # A 20
    # 子类使用父类的方法
    teacher1.eat("rice")                # A正在吃rice
    
    """------子类重写父类的属性、直接使用父类的方法------"""
    class Teacher2(Person):
        def __init__(self, name, age):
            """子类重写父类属性"""
            # Person.__init__(self, name, age)              # 重写构造函数的第一种方法
            super(Teacher2, self).__init__(name, age)       # 重写构造函数的第二种方法
    
    # 子类使用父类的属性
    teacher2 = Teacher2("A", 20)
    print(teacher2.name, teacher2.age)  # A 20
    # 子类直接使用父类的方法
    teacher2.eat("fish")                # A正在吃fish
    
    """------子类重写父类属性且添加新的属性,子类重写父类方法------"""
    class Teacher3(Person):
        def __init__(self, name, age, sex):
            """子类重写父类属性"""
            # Person.__init__(self, name, age)              # 重写构造函数的第一种方法
            super(Teacher3, self).__init__(name, age)       # 重写构造函数的第二种方法
            self.sex = sex
    
        def eat(self, food):
            """子类重写父类方法"""
            print("%s is eating %s" % (self.name, food))
    
    teacher3 = Teacher3("A", 20, "female")
    print(teacher3.name, teacher3.age, teacher3.sex)  # A 20 female
    # 子类直接使用父类的方法
    teacher3.eat("fish")            # A is eating fish
    

    3. 多继承

    多继承即同时继承多个类。

    3.1. 子类属性的继承和重写

    • 子类需要重写父类的构造函数,且也可添加属于自己的新属性。
      子类构造函数中也可添加有新的属性。
    父类1.__init__(self, 参数1, 参数2, ...)
    父类2.__init__(self, 参数1, 参数2, ...)
    ...
    父类n.__init__(self, 参数1, 参数2, ...)
    

    3.2. 子类方法的继承和重写

    • 子类继承多个父类,且父类中存在相同的方法名。
      若子类中未重写此方法,子类使用此方法时,默认调用的是括号中排在前面的父类方法;
      若子类中重写有此方法,则会使用子类中的方法。

    3.3. 子类继承多个父类的例子

    • 子类Person既是程序员又是厨师
    class Programmer(object):       # 程序员
        def __init__(self, language):
            self.language = language
    
        def writeCode(self):
            print("用%s语言写代码" % self.language)
    
        def phone(self):
            print("程序员在打电话")
    
    class Chef(object):         # 厨师
        def __init__(self, food):
            self.food = food
    
        def cooking(self):
            print("烹饪%s" % self.food)
    
        def phone(self):
            print("厨师在打电话")
    
    """------子类继承多个父类,子类重写父类的属性------"""
    class Person1(Programmer, Chef):
    
        def __init__(self, name, age, language, food):
            """子类重写父类属性"""
            Programmer.__init__(self, language)
            Chef.__init__(self, food)
            self.name = name
            self.age = age
    
    # 创建类的实例化对象
    person1 = Person1("A", 18, "Python", "fish")
    # 对象的属性
    print(person1.name, person1.age, person1.language, person1.food)    # A 18 Python fish
    # 子类使用父类方法
    person1.writeCode()         # 用Python语言写代码
    person1.cooking()           # 烹饪fish
    # 父类存在相同的方法,子类使用时默认使用括号中排名在前的方法
    person1.phone()             # 程序员在打电话
    
    """------子类继承多个父类,子类重写父类的属性且重写父类方法------"""
    class Person2(Programmer, Chef):
    
        def __init__(self, name, age, language, food):
            """子类重写父类属性"""
            Programmer.__init__(self, language)
            Chef.__init__(self, food)
            self.name = name
            self.age = age
    
        def phone(self):
            print("%s在打电话" % self.name)
    
    person2 = Person2("A", 20, "Python", "fish")
    person2.phone()         # A在打电话
    

    四、多态

    多态:一种事件的多种形态。意味着即使不知道变量指向什么对象,也能够对此对象执行操作,且操作的行为跟随对象所必的类型而变。

    class Animal(object):
        def __init__(self, name):
            self.name = name
    
        def run(self):
            print("%s在跑步" % self.name)
    
    """采用多态方式实现"""
    class Person(object):
        def leadAnimalRun(self, animal):    # animal采用的多态方式
            print("人训练动物跑步")
            animal.run()
    
    person = Person()
    cat = Animal("Cat")
    person.leadAnimalRun(cat)
    dog = Animal("Dog")
    person.leadAnimalRun(dog)
    

    五、对象属性和类属性

    一个类所包含的属性有:对象属性和类属性。

    1. 类属性

    • 在类中,方法外面定义的变量称为类属性。
      在类的内部和外部,类属性值均可以通过类或对象来访问,但只能通过类来修改。

    1.1. 访问类属性

    • 通过类访问类属性
      在类的内部和外部访问:类名.类属性
    • 通过对象访问类属性
      在类的内部访问:self.类属性
      在类的外部访问:实例化对象.类属性

    1.2. 修改类属性

    • 类名.类属性 = 新值
      通过类来修改类属性值,由于按全局变量的方式修改,则整个类中的此属性值均发生变化。
    • self.类属性 = 新值实例化对象.类属性 = 新值
      此方法相当于把类属性变成实例化对象属性,相当于局部变量,仅会对当前对象生效,对此类创建的其他对象不生效。

    2. 对象属性

    • 在类中,__init()__方法中定义的属性称为对象属性。
      在类的内部访问:self.对象属性
      在类的内部修改值:self.对象属性 = 新值
      在类的外部访问:实例化对象.对象属性
      在类的外部修改值:实例化对象.对象属性 = 新值
    • 可动态的给对象添加新的对象属性,但此对象只对当前对象生效,对此类创建的其他对象无用。
    • 在同一类中,若类属性名与对象属性名相同,则对象属性的优先级高于类属性。
    class Person1(object):
        count = 0                   # 类属性
    
        def __init__(self, name):   # 对象属性
            self.name = name
    
        def testClassAttribute(self):
            """通过类修改类属性值"""
            Person1.count = 50  # 通过类名的方式给类属性值赋新值,相当于全局变量
            print(Person1.count)  # 50
            print(self.count)  # 50
            """通过对象修改类属性值"""
            self.count = 60  # 通过对象的方式给类属性值赋新值,相当于局部变量,仅对当前对象生效
            print(Person1.count)  # 50
            print(self.count)  # 60
    
        def testObjectAttribute(self):
            """对象属性"""
            self.name = 'B'
            print(self.name)    # B
    
    person1 = Person1("A")
    person1.testClassAttribute()
    print(Person1.count)        # 50
    print(person1.count)        # 60
    
    person1.testObjectAttribute()
    person1.name = "C"          # 类外部修改对象属性值
    person1.age = 20            # 类外部新建新的属性,并赋值
    print(person1.name, person1.age)         # C 20
    

    六、动态给实例添加属性和方法

    1. 动态给实例添加属性和方法

    • 动态给实例添加属性
      实例对象.新属性 = 属性值
    • 动态给实例添加方法
      先导入模块from types import MethodType
      实例对象.新方法 = MethodType(方法名, 实例对象)
    class Person(object):
        pass
    
    person = Person()
    """给对象动态添加属性"""
    person.name = "LiMing"
    print(person.name)      # LiMing
    """给对象动态添加方法"""
    from types import MethodType    
    def getAge(self, age):
        print("%s的年龄:%d" % (self.name, age))
    person.ageMethod = MethodType(getAge, person)
    person.ageMethod(20)            # LiMing的年龄:20
    

    2. 限制对象中添加的动态属性

    定义类时定义一个特殊的属性__slots__,此属性可限制动态添加的属性。

    from types import MethodType    
    class Student:
        __slots__ = ("name", "age", "sex", "scoreInfo")      # 表示给Student类添加属性时仅可添加name、age、sex、scoreInfo
    
    student = Student()
    student.name = "LiHong"
    print(student.name)             # LiHong
    # student.work = "Doctor"       # 会报错提示此对象无work属性
    # print(student.work)
    def getScore(self, score):
        print("%s的分数:%d" % (self.name, score))
    student.scoreInfo = MethodType(getScore, student)
    student.scoreInfo(90)           # LiHong的分数:90
    

    七、运算符重载

    对两个对象执行运算操作,则提示类型不支持(TypeError: unsupported operand type(s)),因此需要借助运算符重载。

    1. 常用的运算符重载

    构造函数__init__
    解析函数__del__
    打印函数__repr__、__str__
    函数调用__call__
    函数属性__getattr__、__setattr__、__delattr__
    数字运算符函数:__add__(self, other)、__sub__(self, other)、__mul__(self, other)、__div__(self, other)
    ...
    
    class Student:
        def __init__(self, score):
            self.score = score
    
        def __add__(self, other):
            return Student(self.score + other.score)
    
        def __str__(self):
            return "score=%d" % self.score
    
    student1 = Student(70)
    student2 = Student(80)
    print(student1 + student2)                  # score=150
    print(student1.__add__(student2).score)     # 150
    

    2. __call__介绍:

    __call__是一个可调用对象,而函数和类都属于可调用对象。
    通过__call__方法可以将一个类实例化对象变成一个可调用对象。使用__call__还可以

    class Person:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __call__(self, name, sex):
            self.name = name
            self.sex = sex
    
    person = Person("LiMing", 20, "female")     # 实例化对象
    person("LiHong", "male")                    # 将实例变为可调用的对象
    print(person.name, person.sex, person.age)      # LiHong male 20
    

    相关文章

      网友评论

          本文标题:python3之模块和面向对象

          本文链接:https://www.haomeiwen.com/subject/naxjnqtx.html