技术交流QQ群:1027579432,欢迎你的加入!

1.类和实例

  • 类是抽象的模板,实例是根据类创建出来的一个个具体的"对象"。例如:动物是一大类,猫、狗、鱼等都是特定的对象,即实例。python3中使用class关键字来定义类,基本结构如下:
class 类名(父类/基类/超类列表):
    pass
  • 类名一般使用大驼峰来进行命名,尽量见名知意。python采用多继承的机制,一个类可以同时继承多个父类(基类、超类),继承的父类有先后顺序,写在类名后面的括号中。python3中,object是python3中所有类的基类中,可以省略类名后面的括号,表示隐式继承。
  • 通过类的实例化方法来创建一个类的实例,类似于C++中的构造函数。默认情况下,使用类似stu = Student()的方式就可以生成一个类的实例。但是,实际中一个类的实例也会有属于自己的实例变量。python中提供一个def __init__(self):实例化机制。任何一个类中,名字为__init__()的方法就是类的实例化方法。具有__init__()方法的类在类进行实例化时,会自动调用此方法,并传递对应的参数。如下面所示:
class Student:
        def __init__(self,name, age):
            self.name = name
            self.age = age
        def printInfo(self):
            print("name:{}".format(self.name), "age:{}".format(self.age))
    
    stu1 = Student("curry", 31)
    stu2 = Student("harden", 29)

2.实例变量与类变量

  • 实例变量:实例本身所拥有的变量,每个实例的变量在内存中都不一样。调用方法:实例名.实例变量名
stu1.name
    stu1.age
  • 类变量:定义在类中,但在方法之外的变量。可以通过类名.类变量名或者实例名.类变量名来访问类变量。类变量是所有实例都共同拥有的变量,每个实例都可以访问、修改类变量。例如下面例子中,classroom和address就是两个类变量。注意:当使用stu1.name访问变量时,实例会首先在自己的实例变量中查找是否有此实例变量name,然后再去类变量中进行查找,如果都没有,则抛出异常!
class Student:
        classroom = "101"
        address = "beijing"
        def __init__(self,name, age):
            self.name = name
            self.age = age
        def printInfo(self):
            print("name:{}".format(self.name), "age:{}".format(self.age))
    
    stu1.classroom  # 类变量的访问
    Student.classroom
    stu1.name
  • 因为Python是动态语言的特点,可以随时给实例动态添加新的实例变量,给类添加新的类变量和方法。因此,使用stu1.classroom="110"时,要么是给已有的实例变量classroom重新赋值,要么就是新建一个专属于stu1实例的实例变量,并赋值110,如下面的例子:
class Student:
        classroom = "101"  # 类变量
        address = "beijing"
        def __init__(self,name, age):
            self.name = name
            self.age = age
        def printInfo(self):
            print("name:{}".format(self.name), "age:{}".format(self.age))
    
    stu1 = Student("curry", 31)
    stu2 = Student("harden", 29)
    print(stu1.classroom)    # stu1实例本身没有classroom实例变量,所以去寻找类变量,它找到了!
    Student.classroom  # 通过类名访问类变量
    stu1.classroom = "110"  # 关键的一步!实际是为实例stu1创建了一个独有的实例变量classroom,只不过名字和类变量一样,都叫做classroom。
    print(stu1.classroom)  # 输出110,再次访问的时候,访问到的是stu1自己的实例变量classroom
    del stu1.classroom    # 删除了stu1的实例变量classroom

3.类的方法

  • Python的类中包含实例方法、静态方法和类方法三种方法。
    • 实例方法:类的实例方法由实例调用,至少包含一个self参数,且为第一个参数。执行实例方法时,自动将调用该方法的实例赋值给self。self代表的是类的实例,而非类本身。self不是关键字,而是Python约定成俗的命名,你完全可以取别的名字,但不建议这么做。 例如下面的方法printInfo(self):
    def printInfo(self):
                print("name:{}".format(self.name), "age:{}".format(self.age))
    • 静态方法:静态方法由类调用,无默认参数。将实例方法参数中的self去掉,然后在方法定义上方加上@staticmethod,就成为静态方法,它属于类,和实例无关。建议只使用类名.静态方法调用方式。(虽然也可以使用实例名.静态方法的方式调用)
    class Foo:
            @statcimethod:
            def static_method():
                pass
        # 调用
        Foo.static_method()
    • 类方法:类方法由类调用,采用@classmethod装饰,至少传入一个cls(代指类本身,类似self)参数。执行类方法时,自动将调用该方法的类赋值给cls。建议只使用类名.类方法的调用方式。(虽然也可以使用实例名.类方法的方式调用)
    class Foo:
            @classmethod
            def bar_method(cls):
                pass
        # 调用
        Foo.bar_method()
  • 综合实例如下:
class Foo:
        def __init__(self,name):
            self.name = name
        def ord_func(self):  # 定义实例方法,至少有一个self参数
            print("实例方法")
        
        @classmethod
        def class_func(cls):  # 定义类方法,至少有一个cls参数
            print("类方法")
        
        @staticmethod
        def static_func():  # 定义静态方法 ,无默认参数
            print("静态方法")
            
    # 调用实例方法
    f = Foo("Jack")
    f.ord_func()
    Foo.ord_func(f) # 请注意这种调用方式,虽然可行,但建议不要这么做!
    
    # 调用类方法
    Foo.class_func()
    f.class_func()  # 请注意这种调用方式,虽然可行,但建议不要这么做!
    
    # 调用静态方法
    Foo.static_func()
    f.static_func() # 请注意这种调用方式,虽然可行,但建议不要这么做!

4.类、类的方法、类变量、类的实例和实例变量在内存中是如何保存的?

  • 类、类的所有方法以及类变量在内存中只有一份,所有的实例共享它们。而每一个实例都在内存中独立的保存自己和自己的实例变量。创建实例时,实例中除了封装诸如name和age的实例变量之外,还会保存一个类对象指针,该值指向实例所属的类的地址。因此,实例可以寻找到自己的类,并进行相关调用,而类无法寻找到自己的某个实例。
    image

5.参考博客