Python面向对象(一)之类的构建

类的基本构建

  • 使用class保留字定义类
    class <类名>:
           [类描述 documentation string]
           <语句块>
    类定义不限位置,可以包含在分支或其他从属语句块中,执行时存在即可。
    类的名字:可以是任何有效标识符。建议采用大写单词的组合。
    如ClassName, SortTest, MyModule …
    类的描述:在类定义首行,以字符串定义。定义后通过<类名>.__doc__属性来访问

    class DemoClass:
        "This is a DemoClass for Python"
        pass
    print(DemoClass.__doc__)
    

    输出

    This is a DemoClass for Python

  • 类对象 Class Object

    • 类定义完成后,默认生成一个类对象
    • 每个类唯一对应一个类对象,用于存储这个类的基本信息
    • 类对象是type类的实例,表达为type类型
    class DemoClass:
        "This is a DemoClass for Python"
        print("Hello, DemoClass!")
    print(DemoClass.__doc__)
    print(type(DemoClass))
    

    输出

    Hello, DemoClass!
    This is a DemoClass for Python

    类对象内直接包含的语句会被执行,因此一般不在类内直接包含执行语句,一般放在类的方法中。


类的使用

  • 通过创建实例对象(Instance Object)使用类的功能
    <对象名> = <类名>([<参数>])
    进一步采用<对象名>.<属性名>和<对象名>.<方法名>()体现类的功能

    class DemoClass:
        "This is a DemoClass for Python"
        print("Hello, DemoClass!")
    print(type(DemoClass))
    dc = DemoClass()
    print(type(dc))
    

    输出

    Hello, DemoClass!

    main.DemoClass’>

    实例对象是Python类的最常用方式
    类对象全局只有一个,而实例对象可以生成多个


类的构造函数

  • Python使用预定义的__init__()作为构造函数

    class <类名>def __init__(self, <参数列表>)<语句块>
    	...
    
    class DemoClass:
    	def __init__(self, name):
    		print(name)
    dc1 = DemoClass('老李')
    dc2 = DemoClass('老王')
    

    输出

    老李
    老王
    通过构造函数__init__()可以为Python对象提供参数

  • __init__的使用说明

    • 参数:第一个参数约定是self,表示类实例自身,其他参数是实例参数
      你一定会在想python如何给self赋值,以及为何你不必给它一个值。下面举个简单的例子:假设你有一个MyClass的类,这个类下有个实例myobject。当你调用一下这个对象的方法,如myobject.method(arg1, arg2)时,python将会自动将其转换成MyClass.method(myobject, arg1, arg2)。这就是self的神奇所在。
  • 函数名:python解释器内部定义,由双下划线(__)开始和结束

  • 返回值:构造函数没有返回值,或返回None,否则产生TypeError异常


类的属性

  • 属性是类内部定义的变量

    • 类属性:类对象的属性,由所有实例对象所共享
      访问:<类名>.<类属性> 或<对象名>.<类属性>
    • 实例属性:实例对象的属性,由各实例对象所独享
      访问:<对象名>.<实例属性>
    class <类名><类属性名> = <类属性初值>
    	def __init__(self, <参数列表>):
    			self.<实例属性名> = <实例属性初值>
    	...
    
    class DemoClass:
    	count = 0
        def __init__(self, name, age):
            self.name = name
            self.age = age
            DemoClass.count += 1
    dc1 = DemoClass('老李', 45)
    dc2 = DemoClass('老王', 50)
    print('总数:', DemoClass.count)
    print(dc1.name, dc2.name)
    print(dc1.age, dc2.age)
    

    输出

    总数: 2
    老李 老王
    45 50

    类属性 直接在类中定义或赋值
    统一用<类名>.<属性名>访问

    实例属性
    在类内部 用self.<属性名>访问
    在类外部 用<对象名>.<属性名>访问


类的方法

方法是类内部定义的函数

  • 实例方法:实例对象的方法,由各实例对象独享,最常用的形式。

    class <类名>:
    	def <方法名>(self, <参数列表>)...
    

    实例方法采用<对象名>.<方法名>(<参数列表>)方式使用

    class DemoClass:
        def __init__(self, name):
            self.name = name
        def lucky(self):
            s = 0
            for c in self.name:
                s += ord(c) % 100
            return s
    dc1 = DemoClass('老李')
    dc2 = DemoClass('老王')
    print(dc1.name, "的幸运数字是", dc1.lucky())
    print(dc2.name, "的幸运数字是", dc2.lucky())
    

    输出

    老李 的幸运数字是 115
    老王 的幸运数字是 148

    实例方法的定义 第一个参数是self

  • 类方法:类对象的方法,由所有实例对象共享。

    • 类方法至少包含一个参数,表示类对象,建议用cls
    • @classmethod是装饰器,类方法定义所必须
    • 类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法
    class DemoClass:
    	count = 0
        def __init__(self, name):
            self.name = name
            DemoClass.count += 1
        
        @classmethod
        def getChrCount(cls):
            s = '零一二三四五六七八九十'
            return s[DemoClass.count]
    
    dc1 = DemoClass('老李')
    dc2 = DemoClass('老王')
    print(dc1.getChrCount())
    print(DemoClass.getChrCount())
    

    输出


  • 自由方法:类中的普通函数,由类所在命名空间管理,类对象独享。

    class <类名>def <方法名>(<参数列表>):
    		...
    

    自由方法采用<类名>.<方法名>(<参数列表>)方式使用,<类名>表示命名空间

    • 自由方法不需要self和cls这类参数,可以没有参数
    • 自由方法只能操作类属性和类方法,不能操作实例属性和实例方法
    • 自由方法的使用只能使用<类名>
      class DemoClass:
          count = 0
          def __init__(self, name):
              self.name = name
              DemoClass.count += 1
          def foo():
              DemoClass.count *= 100
              return DemoClass.count
      
      dc1 = DemoClass('老王')
      print(DemoClass.foo())
      
  • 静态方法:类中的普通函数,由类对象和实例对象共享。

    class <类名>:
    	@staticmethod
    	def <方法名>(<参数列表>):
    		...
    

    静态方法采用<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)方式使用

    • 静态方法可以没有参数,可以理解为定义在类中的普通函数
    • @staticmethod是装饰器,静态方法定义所必须
    • 静态方法只能操作类属性和其他类方法,不能操作实例属性和实例方法
    • 相比于自由方法,静态方法能够使用<类名>和<对象名>两种方式使用
      class DemoClass:
          count = 0
          def __init__(self, name):
              self.name = name
              DemoClass.count += 1
              
          @staticmethod
          def foo():
              DemoClass.count *= 100
              return DemoClass.count
          
      dc1 = DemoClass('老王')
      print(DemoClass.foo())
      print(dc1.foo())
      
      输出

      100
      10000

  • 保留方法:由双下划线开始和结束的方法,保留使用,如__len__()

    class <类名>:
    	def <保留方法名>(<参数列表>):
    		...
    

    保留方法一般都对应类的某种操作,操作产生时调用

    class DemoClass:
        count = 0
        def __init__(self, name):
            self.name = name
            DemoClass.count += 1
            
        def __len__(self):
            return len(self.name)
    	    
    dc1 = DemoClass('老王')
    dc2 = DemoClass('诸葛亮')
    print(len(dc1))
    print(len(dc2))
    

    输出

    2
    3

    当对类执行len()方法时,将会执行类的__len__()保留方法,我们只需要在保留方法中编写代码即可执行相应的操作。


类的析构函数

  • Python使用预定义的__del__()函数作为析构函数
    class <类名>:
    	def __del__(self):
    		<语句块>
    	...
    
    析构函数在真实删除实例对象时被调用
    class DemoClass:
        def __init__(self, name):
            self.name = name
        def __del__(self):
            print("再见!", self.name)
            
    dc1 = DemoClass('老王')
    del dc1
    
    使用del删除对象且对象被真实删除时调用析构函数__del__()
    __del__()的使用说明:
    • 函数名和参数:Python解释器内部约定,保留方法

    • 调用条件:当实例对象被真实删除时,才调用该函数内部语句

    • 真实删除:当前对象的引用数为0或当前程序退出(垃圾回收)

      class DemoClass:
          def __init__(self, name):
              self.name = name
          def __del__(self):
              print("再见!", self.name)
              
      dc1 = DemoClass('老王')
      dc2 = dc1
      del dc1
      print(dc2.name)
      

      输出

      老王
      再见!老王

      由于删除dc1对象时,还存在dc2这个引用,因此并未真实删除对象,所以析构函数未被调用,当程序执行完,dc2这个引用被自动销毁,此时再调用析构函数,输出”再见!老王“。一般不需要写析构函数,让Python的垃圾回收机制去处理。这里了解就可以~
      Python类的内存管理

      • 在删除对象前,Python解释器会检查引用次数
      • 引用次数不为0,则仅删除当前引用;0,则删除对象
      • 如果程序退出,则由垃圾回收机制删除对象

你可能感兴趣的:(Python)