【python基础】类定义和使用

文章目录

  • 1. 类的定义和使用
  • 2. 对象的三大特性
  • 2.1 封装
  • (1)通过对象调用被封装的内容
  • (2)通过self间接访问被封装的内容
  • 2.2 继承
  • 2.3 多态
  • 3. 属性(变量)绑定
  • 3.1 类属性绑定
  • 3.2 实例属性绑定
  • 4. 属性引用
  • 4.1 类属性引用
  • 4.2 实例属性引用
  • 4.3 可变类属性引用
  • 4.4 一个例子说明类属性、实例属性与普通变量
  • 5. 方法
  • 5.1 实例方法、类方法和静态方法
  • 5.2 实例方法中调用其它方法
  • 1. 类的定义和使用

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量(类属性):类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 实例变量(实例属性):定义在方法中的变量,只作用于当前实例的类。
  • 方法:类中定义的函数。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,所以Dog也是一个Animal。
  • 实例化:创建一个类的实例,类的具体对象
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法
  • 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。

    一个典型的类的定义和使用例子如下:

    #创建类
    class Foo: #class是关键字,Foo是类名
      class_int = 10 #类变量
      #创建类中的函数(方法)
      def bar(self,name):   #self是特殊参数,类的实例化,必须填写。
        print('bar')
    
    obj = Foo() #根据Foo创建对象obj
    print('类访问类变量:',Foo.class_int)
    print('对象访问类变量:', obj.class_int)
    obj.bar(3)
    

    输出:

    类访问类变量: 10
    对象访问类变量: 10
    bar
    

    类的使用请注意:

    1. 调用类属性:
      ⑴类中访问类变量:类名. 类变量名
      ⑵类外访问类变量:类名.类变量名或实例名.类变量名
    2. 调用实例属性:
      ⑴类中访问实例变量:self.实例变量名
      ⑵类外访问实例变量:实例名.实例变量名
    3. 调用实例方法:
      ⑴类中访问实例方法:self.方法名(参数)或类名.方法名(self,参数)
      ⑵类外访问实例方法:实例名.方法名(参数)

    2. 对象的三大特性

    和所有的面向对象语言一样,python对象也有三大特性,它们分别为封装、继承和多态

    2.1 封装

    封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

    (1)通过对象调用被封装的内容

    通过:对象.属性名的方式访问实例化对象。具体访问形式如下:

    class Foo:
      def __init__(self, name, age):
        self.name = name
        self.age = age
    
    obj = Foo('xiaoming', 22)
    print(obj.name,obj.age)
    print(type(obj))
    

    输出:

    xiaoming 22
    <class '__main__.Foo'>
    

    (2)通过self间接访问被封装的内容

    其实self就是实例化对象本身,所以可以通过它对实例化对象进行访问。

    class Foo:
      def info(self):
        print(self.name,self.age)
      def __init__(self, name, age):
        self.name = name
        self.age = age
    
    obj = Foo('xiaoming', 22)
    obj.info()
    

    输出:

    xiaoming 22
    

    2.2 继承

    和现实中一样,子类可以继承父类中的内容。比如,首先创建一个Animal类,然后cat和dog分别继承它。

    class Animal:
        def eat(self):
            print("%s 吃 " % self.name)
        def drink(self):
            print("%s 喝 " % self.name)
        def shit(self):
            print("%s 拉 " % self.name)
        def pee(self):
            print("%s 撒 " % self.name)
    
    class Cat(Animal):
        def __init__(self, name):
            self.name = name
            self.breed = '猫'
        def cry(self):
            print('喵喵叫')
    
    class Dog(Animal):
        def __init__(self, name):
            self.name = name
            self.breed = '狗'
        def cry(self):
            print('汪汪叫')
    
    # ######### 执行 #########
    
    c1 = Cat('小明家的小猫')
    c1.eat()
    
    d1 = Dog('小红家的小狗')
    d1.eat()
    
    小明家的小猫 吃 
    小红家的小狗 吃
    

    2.3 多态

    python中的多态,不像C++中父类与子类中的多态一样。它需要根据对象的具体指向来决定方法的指向。具体示例如下,S1和S2都实现了show方法,具体看它的指向来决定调用哪一个。

    class F1:
        pass
    
    class S1(F1):
        def show(self):
            print('S1.show')
    
    class S2(F1):
        def show(self):
            print('S2.show')
    
    def Func(obj):
        obj.show()
    
    s1_obj = S1()
    Func(s1_obj)
    
    s2_obj = S2()
    Func(s2_obj) 
    

    输出:

    S1.show
    S2.show
    

    3. 属性(变量)绑定

    Python作为动态语言,类对象和实例对象都可以在运行时绑定任意属性。因此,类属性的绑定发生在两个地方,类定义时和运行的任意阶段

    3.1 类属性绑定

    下面程序中介绍了类中和类外的类属性绑定方法,同时类属性也可以被删除

    class Dog:
        kind = 'canine' #类中,类属性绑定
    
    Dog.country = 'China'  # 类外,类属性绑定
    
    print(Dog.kind, ' - ', Dog.country)  # 输出: canine  -  China
    del Dog.kind #删除类属性
    print(Dog.kind, ' - ', Dog.country)  # 类属性被删除,报错!
    

    输出:

    canine  -  China
    Traceback (most recent call last):
      File "/home/liqiang/workspace/python/python_tutorials/main.py", line 8, in <module>
        print(Dog.kind, ' - ', Dog.country)  # 类属性被删除,报错!
    AttributeError: type object 'Dog' has no attribute 'kind'
    

    3.2 实例属性绑定

    与类属性绑定相同,实例属性绑定也发生在两个地方:类定义时、运行时任意阶段。

    class Dog:
        def __init__(self, name, age):
            self.name = name #类中,实例绑定
            self.age = age
    
    dog = Dog('Lily', 3)
    dog.fur_color = 'red'  # 类外,实例属性绑定
    
    print('%s is %s years old, it has %s fur' % (dog.name, dog.age, dog.fur_color))
    

    输出:

    Lily is 3 years old, it has red fur
    

    4. 属性引用

    4.1 类属性引用

    类属性分为两种:数据属性、方法属性。只是通常很少有引用类函数属性的需求。

    数据属性

    class Dog:
        kind = 'canine'
    
    Dog.country = 'China'
    
    print(Dog.kind, ' - ', Dog.country) #这两个都是类数据属性的引用
    

    输出:

    canine  -  China
    

    4.2 实例属性引用

    实例对象可以引用类属性和实例属性,遵循的规则如下:

    1. 先查找实例属性,后查找类属性
    2. 属性绑定时,总是为实例对象创建新属性(即使存在相同的类属性),属性存在时,只更新属性执行的对象

    代码示例1:

    class Dog:
        kind = 'canine'
        country = 'China'
    
        def __init__(self, name, age, country):
            self.name = name
            self.age = age
            self.country = country
    
    dog = Dog('Lily', 3, 'Britain')
    print(dog.name, dog.age, dog.kind, dog.country)
    

    输出:

    Lily 3 canine Britain
    

    说明:类对象Dog与实例对象dog均有属性country,按照规则,dog.country会引用到实例对象的属性;但实例对象dog没有属性kind,按照规则会引用类对象的属性。

    代码实例2:

    class Dog:
        kind = 'canine'
        country = 'China'
    
        def __init__(self, name, age, country):
            self.name = name
            self.age = age
            self.country = country
    
    
    dog = Dog('Lily', 3, 'Britain')
    
    print(dog.name, dog.age, dog.kind, dog.country)
    print(dog.__dict__)
    
    dog.kind = 'feline' #新增实例属性,不会改变类属性的值
    
    print(dog.name, dog.age, dog.kind, dog.country)
    print(dog.__dict__)
    print(Dog.kind) #类属性并没有改变
    

    输出:

    Lily 3 canine Britain
    {'name': 'Lily', 'age': 3, 'country': 'Britain'}
    Lily 3 feline Britain
    {'name': 'Lily', 'age': 3, 'country': 'Britain', 'kind': 'feline'}
    canine
    

    说明:类外使用新增实例属性,并不会影响类属性

    4.3 可变类属性引用

    下列代码中 self.tricks.append(trick)为可变类属性引用,而不是实例属性!

    class Dog:
        tricks = []
    
        def __init__(self, name):
            self.name = name
    
        def add_trick(self, trick):
            self.tricks.append(trick) #这里是可变的类属性引用,而不是实例子属性
    
    
    d = Dog('Fido')
    e = Dog('Buddy')
    d.add_trick('roll over')
    e.add_trick('play dead')
    print(d.tricks)
    

    输出:

    ['roll over', 'play dead']
    

    如果想要使用实例属性,可以在先定义self.tricks,然后再append。如下:

    class Dog:
        tricks = []
    
        def __init__(self, name):
            self.name = name
    
        def add_trick(self, trick):
            self.tricks = []
            self.tricks.append(trick) 
    
    
    d = Dog('Fido')
    e = Dog('Buddy')
    d.add_trick('roll over')
    e.add_trick('play dead')
    print(d.tricks)
    print(e.tricks)
    

    输出:

    ['roll over']
    ['play dead']
    

    4.4 一个例子说明类属性、实例属性与普通变量

    class TestClass(object):
        val1 = 100
    
        def __init__(self):
            self.val2 = 200
    
        def fcn(self, val=400):
            val3 = 300
    
            self.val4 = val
            self.val5 = 500
    
    
    if __name__ == '__main__':
        inst = TestClass()
    
        print(TestClass.val1)
        print(inst.val1)
        print(inst.val2)
        #print(inst.val3) # val3为局部变量,报错!!!
        #print(inst.val4) # val4不是实例属性,报错!!!
        #print(inst.val5)# val5不是实例属性,报错!!!
        print(inst.__dict__)
    

    输出:

    100
    100
    200
    {'val2': 200}
    

    可以看出inst只有一个实例属性,也就是val2

    1. val1是类变量,可以由类名直接调用,也可以有对象来调用;
    2. val2是实例变量,可以由类的对象来调用,这里可以看出成员变量一定是以self.的形式给出的,因为self的含义就是代表实例对象
    3. val3既不是类变量也不是实例变量,它只是函数fcn内部的局部变量
    4. val4和val5也都不是实例变量,虽是以self.给出,但并没有在构造函数中初始化

    5. 方法

    5.1 实例方法、类方法和静态方法

  • 实例方法:一般在类中定义的方法,默认都为实例方法。实例方法最大的特点就是最少要包含一个self参数,该参数必须定义,但调用时不需要传。类比C++中的this指针。
  • 类方法:类方法至少需要包含一个参数(cls),但在调用类方法时,无需显式为cls参数传递参数。类方法需要使用修饰语句: @classmethod类和实例对象都可以调用类方法
  • 静态方法与普通函数类似,只是它在类命名空间中定义,而函数实在程序的全局命名空间中定义。它有以下特点:
    1. 类静态方法没有self、cls这样的特殊参数;
    2. 类静态方法中无法调用任何类和对象的属性和方法,类静态方法与类的关系不大;
    3. 静态方法需要使用@staticmethod修饰;
    4. 可以使用类或实例对象调用它。
  • 类方法举例
  • class CLanguage:
        def __init__(self):
            self.name = "小明"
            self.age = "22"
    
        # 下面定义了一个类方法
        @classmethod
        def info(cls):
            print("正在调用类方法", cls)
    
    
    # 使用类名直接调用类方法
    CLanguage.info()
    # 使用类对象调用类方法
    clang = CLanguage()
    clang.info()
    

    输出:

    正在调用类方法 <class '__main__.CLanguage'>
    正在调用类方法 <class '__main__.CLanguage'>
    
  • 静态方法举例
  • class CLanguage:
        @staticmethod
        def info(name, age):
            print(name, age)
    
    
    # 使用类名直接调用静态方法
    CLanguage.info("xiaoming", "22")
    
    # 使用类对象调用静态方法
    clang = CLanguage()
    clang.info("xiaohong", "23")
    

    输出:

    xiaoming 22
    xiaohong 23
    

    5.2 实例方法中调用其它方法

    内部调用实例方法需要加slef

    class Dog():
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def get_dog_information(self):
            dog_information = "name is {0},age is {1}".format(self.name, self.age)
            return dog_information
    
        def get_dog_speak(self, love):
            dog_speak = self.get_dog_information() + love #内部调用实例方法
            return dog_speak
    
    
    dog = Dog("jake", 13)
    print(dog.get_dog_speak("swimming"))
    

    输出:

    name is jake,age is 13swimming
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 【python基础】类定义和使用

    发表评论