• python 基础篇 类基础与继承


    先来简单解释几个概念

    • 类:一群有着相同属性和函数的对象的集合,这里对应 Python 的 class。
    • 对象:集合中的一个事物,这里对应由 class 生成的某一个 object,比如代码中的 harry_potter_book。
    • 属性:对象的某个静态特征,比如上述代码中的 title、author 和 __context
      • 私有属性:是指不希望在类的函数之外的地方被访问和修改的属,以 __ (注意,此处有两个 _) 开头,就默认这个属性是私有属性。
    • 函数或方法:对象的某个动态能力,比如代码中的 intercept_context () 函数

    属性和方法分类

    属性

    • 类属性 (属于类,每个类一份)
    • 实例属性 (属于对象,每个对象一份)

    方法(按作用)

    • 构造方法 __init__
    • 析构函数 __del__
    • 显示函数 __str__

    方法(按类型)

    • 类方法
    • 实例方法
    • 静态方法

    简单示例

    这里不区分公有属性和私有属性,公有属性和私有属性相对于类内和类外来说的。

    class Document():
        # 类属性,又称静态属性
        # 类和对象都可以方便访问这些常量而不用重新构造
        # 类中使用 self.WELCOME_STR ,或者在类外使用 Entity.WELCOME_STR
        WELCOME_STR = 'Welcome! The context for this book is {}.'
        
        # 构造函数
        # 把要先初始化的属性放到这个函数里
        def __init__(self, title, author, context):
            print('init function called')
            
            # 实例属性
            # 调用:被对象调用
            # 
            self.title = title
            self.author = author
            self.__context = context
        
        # 类方法
        # 定义:用 @classmethod 装饰且第一个参数一般为 cls
        # 调用:可以被类或者对象调用
        # 变量范围:类方法只能访问类属性(静态属性),不能访问实例属性(动态属性)
        # 场景:使用在与类进行交互,但不和其 实例 进行交互的函数方法上
        # 例子:类函数最常用的功能是实现不同的 init 构造函数,比如上文代码中,我们使用 create_empty_book 类函数,来创造新的书籍对象
        @classmethod
        def create_empty_book(cls, title, author):
            return cls(title=title, author=author, context='nothing')
        
        # 实例方法,又叫普通方法
        # 定义:第一个参数 self 代表当前对象的引用,可以通过此函数
        # 调用:只能被对象调用
        # 场景:来实现想要的查询/修改类的属性等功能
        # 
        def get_context_length(self):
            # return len(self.__context)
            return len(self.WELCOME_STR)
        
        # 静态方法
        # 定义:用 @staticmethod 装饰的不带 self 参数的方法
        # 调用:可以被类或者对象调用
        # 场景:修饰的方法是放在类外的函数,我们为了方便将他移动到了类里面,它对类的运行无影响
        # 当使用了静态方法后,该函数下无法在调用类的变量和实例的变量。
        # 静态方法名义上归类管理,实际中在静态方法中无法访问类和实例中的任何属性。
        @staticmethod
        def get_welcome(context):
            return Document.WELCOME_STR.format(context)
        
        # 显示函数
        # str函数或者print函数--->obj.__str__()
        # repr或者交互式解释器--->obj.__repr__()
        # str函数或者print函数如果__str__没有被定义,那么就会使用__repr__来代替输出
        # str函数或者print函数如果__str__被定义,那么__repr__就不会执行
        # 注意:这俩方法的返回值必须是字符串,否则抛出异常
        def __str__(self):
            return "test class"
        
        # 析构函数
        # 可以用来释放内存空间
        # 比如关闭数据库的连接
        def __del__(self):
    		pass
    
    empty_book = Document.create_empty_book('What Every Man Thinks About Apart from Sex', 'Professor Sheridan Simove')
    
    print(Document.WELCOME_STR)
    print(empty_book.get_context_length())
    print(empty_book.get_welcome('indeed nothing'))
    print(empty_book.welcome)
    
    doc = Document('a', 'b', 'c')
    print(doc)
    
    # 输出
    # init function called
    # Welcome! The context for this book is {}.
    # 41
    # Welcome! The context for this book is indeed nothing.
    # Welcome! The context for this book is {}.
    # init function called
    # test class
    

    继承

    类的继承,顾名思义,指的是一个类既拥有另一个类的特征,也拥有不同于另一个类的独特特征。在这里的第一个类叫做子类,另一个叫做父类,特征其实就是类的属性和函数。

    class Entity():
        def __init__(self, object_type):
            print('parent class init called')
            self.object_type = object_type
        
        def get_context_length(self):
            raise Exception('get_context_length not implemented')
        
        def print_title(self):
            print(self.title)
    
    class Document(Entity):
        def __init__(self, title, author, context):
            print('Document class init called')
            Entity.__init__(self, 'document')
            self.title = title
            self.author = author
            self.__context = context
        
        def get_context_length(self):
            return len(self.__context)
        
    class Video(Entity):
        def __init__(self, title, author, video_length):
            print('Video class init called')
            Entity.__init__(self, 'video')
            self.title = title
            self.author = author
            self.__video_length = video_length
        
        def get_context_length(self):
            return self.__video_length
    
    harry_potter_book = Document('Harry Potter(Book)', 'J. K. Rowling', 'Forever Do not believe any thing is capable of thinking independently ...')
    harry_potter_movie = Video('Harry Potter(Movie)', 'J. K. Rowling', 120)
    
    print(harry_potter_book.object_type)
    print(harry_potter_movie.object_type)
    
    harry_potter_book.print_title()
    harry_potter_movie.print_title()
    
    print(harry_potter_book.get_context_length())
    print(harry_potter_movie.get_context_length())
    
    ########## 输出 ##########
    
    # Document class init called
    # parent class init called
    # Video class init called
    # parent class init called
    # document
    # video
    # Harry Potter(Book)
    # Harry Potter(Movie)
    # 77
    # 120
    

    在这段代码中,DocumentVideo 它们有相似的地方,都有相应的标题、作者和内容等属性。可以从中抽象出一个叫做 Entity 的类,来作为它俩的父类。

    1. 需要注意的是构造函数。每个类都有构造函数,继承类在生成对象的时候,是不会自动调用父类的构造函数的,因此你必须在 init() 函数中显式调用父类的构造函数。它们的执行顺序是 子类的构造函数 -> 父类的构造函数

    2. 需要注意父类 get_context_length() 函数。如果使用 Entity 直接生成对象,调用 get_context_length() 函数,就会 raise error 中断程序的执行。这其实是一种很好的写法,叫做函数重写,可以使子类必须重新写一遍 get_context_length() 函数,来覆盖掉原有函数。

    3. 注意到 print_title() 函数,这个函数定义在父类中,但是子类的对象可以毫无阻力地使用它来打印 title,这也就体现了继承的优势:减少重复的代码,降低系统的熵值(即复杂度)。

  • 相关阅读:
    js 面试的坑:变量提升
    meta 标签大全
    一个极为简单的requirejs实现
    AMD 的 CommonJS wrapping
    浅解析js中的对象
    javascript运动系列第二篇——变速运动
    开发汉澳即时通信网,2006年上线,QQ死期到了
    SpringMVC中的异步提交表单
    HDU 3698 DP+线段树
    黑马程序猿_反射、内省、泛型
  • 原文地址:https://www.cnblogs.com/hiyang/p/12634703.html
Copyright © 2020-2023  润新知