一 : 类和对象
类:具有相同属性和技能的一类事物.
对象: 具体的类的表现,具体的实实在在的一个实例.
举例说明 : 人和猫都是动物,那么动物就是一个类,人和猫就是两个对象.
二 : 定义和组成
通过关键字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,这个必须要知道.