一 : 类和对象

  类:具有相同属性和技能的一类事物.

  对象: 具体的类的表现,具体的实实在在的一个实例.

  举例说明 : 人和猫都是动物,那么动物就是一个类,人和猫就是两个对象.

二 : 定义和组成

  通过关键字class定义一个类,通过类名()的形式生成一个对象,这个行为称作实例化.

class className():
    类的内容

  类的内容分为两部分:变量部分和函数(方法)部分.下面看一个Person类,类名的首字母都要大写

class Person:
    mind = '有思想'  
    animal = '高级动物'
    faith = '有信仰'

    def __init__(self,name,age,hobby):
        self.name = name  
        self.age = age
        self.hobby = hobby

    def work(self):  
        print('%s都会工作...' %self.name)

    def shop(self):
        print('人类可以消费....')

  mind,animal,faith都是静态变量,__init__(),work(),shop()三个是定义在类中的方法,称作普通方法.

三 : 使用一个类

  在一个类中,可以直接使用静态变量,比如在类中(方法外)print一下一个变量,是完全可以的;对于普通方法,需要将类实例化之后用获得的对象来调用普通方法.

  在类的外面,可以通过  类名.变量名  的方法获得变量的值, 同样的方法也可以调用类里的普通方法,不过需要传入一个参数,不过这种调用方法的方式不推荐.

print(Person.mind, Person.animal, Person.faith) # 有思想 高级动物 有信仰
Person.shop('asfdsf') # 人类可以消费....

  将类实例化之后,可以通过对象或者类中的变量,调用类中的方法.

a = Person('rubby', 10, 'sleeping')
print(a.mind, a.animal, a.faith) # 有思想 高级动物 有信仰
a.work() #rubby会工作...
a.shop() #人类可以消费....

  不仅仅可以获得值,我们还可以进行修改和删除:

print(a.mind) # 有思想
a.mind = '没智商'
print(a.mind) # 没智商
print(Person.mind) # 有思想
del a.mind
print(a.mind) # 有思想

  这个现象需要从内存的角度来解释 : 当创建了一个类之后,内存中会出现一个属于这个类的空间,其中储存着类中的静态变量/方法名/方法的内存地址(类的方法具体是储存在类外面的),实例化之后,类外面单独为这个对象创建了一个空间,其中储存着属于对象的变量和一个指向创建它的类的指针,从对象的角度是无法修改类中的变量的值的,所以第二行只是在对象的空间里创建了一个名为mind的变量,它的值为'没智商',这时打印对象的mind,解释器会先去对象空间中找是否存在名为mind的变量,如果找到了就用它,所以这时打印类中的mind和对象的mind会得到不同的值,当使用del删除对象空间的mind之后,因为解释器从对象空间中找不到,就去所属的类中找,所以这时的mind就是类中的mind的值了.

  为了佐证,我们另外给对象赋一个值abc:

a.abc = 'abc'
print(a.abc) # abc
print(Person.abc) # 报错 AttributeError: type object 'Person' has no attribute 'abc'

  变量abc只存在于对象的空间里.

  除了使用万能的  .  的方法,还可以使用__dict__()这个函数获得类或者对象的空间有哪些东西:

print(Person.__dict__) #{'__module__': '__main__', 'mind': '有思想', 'animal': '高级动物', 'faith': '有信仰', '__init__': <function Person.__init__ at 0x000001FC5DA88268>, 'work': <function Person.work at 0x000001FC5DA882F0>,
    # 'shop': <function Person.shop at 0x000001FC5DA88378>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
print(a.__dict__) # {'name': 'rubby', 'age': 10, 'hobby': 'sleeping', 'abc': 'abc'}

  可以看到,类中除了定义的三个变量和三个方法外,还有__module__,__dict__,__weakref__三个方法和__doc__一个变量,而对象a中除了实例化的时候传入的name,age,hobby三个变量外,还有我们后来加的abc变量.

四 : 类的初始化

  对于类中定义的三个方法,从名字中我们就可以看出__init__()方法和work(),shop()两个方法的不同,这个方法就是初始化方法--初始化(Initialization).

  如果在其中加入一行,让他打印一行字,我们看会有什么效果:

  

    def __init__(self,name,age,hobby):
        self.name = name  #  Person.money = '运用货币'
        self.age = age
        self.hobby = hobby
        print('喵喵喵')
        print(self)

p = Person('rubby', 10, 'sleeping') #喵喵喵 #<__main__.Person object at 0x000001FFDCB8B780>

 

  可以看到,我们进行实例化的时候就打印了喵喵喵和一个地址,而且这个方法我们没有主动调用它,这说明这个方法是在类实例化对象的时候自动触发的,他的作用就是给这个对象进行初始化设置.

  那么在实例化的时候究竟发生了什么呢?

  主要有以下三步: 1. 为对象开辟一个空间 2.将对象的地址和括号中的参数传入__init__()方法,其中地址是自动传且必须传的,别的参数作为位置参数传入,然后在该方法中进行初始化 3. 将初始化完成的对象传给变量p.

  在__init__方法的 参数中,第一个总是接收地址的,形参名没有强制性的命名,但是作为一种规范,大家都使用self.初始化的过程就是给这个self附加各种属性的过程,为了方便,我们把self中的存储name的变量也命名为name,self.name = name这一行中,左边的name是当场给self的一个属性命名为name,等号右边的name则是形参name,这个必须要知道.