类造就万物-面向对象二
上一章节主要阐述了类相关的概念和创建类的基本语法,我们知道类是由数据属性和函数属性结合的,由类可以产生对象,这个过程也叫做实例化,我们得到的结果就是实例,所以实例就是对象,是由类这样一个模板所产生的,那么既然实例(对象)是由类产生的,问题来了,请问实例是否能使用类的数据属性和函数属性呢,我们带着这个问题来一步一步学习
-
类的数据属性和函数属性在什么地方被存储?
我们知道如何去定义一个类,如下:
class Person:
x = 1 #数据属性
def func(self): #函数属性
pass
我们定义了一个Person类,其中包含了数据属性x和函数属性func,那么这些属性被存储在什么地方,下面介绍一个变量叫属性字典,这个字典就将类的数据属性和函数属性存储起来,具体的操作如下:
print(Person.__dict__) #类名.__dict__
通过上述方式就能访问属性字典,我们会得到如下结果
{'__module__': '__main__', 'x': 1, 'func': <function Person.func at 0x02D30228>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
我们可以看到无论是函数属性还是数据属性,在字典中的变成了键,并且键的类型是字符串,如果你只想得到访问函数属性,操作如下
print(Person.__dict__['func'])
值得注意的是我们的键必须是字符串
-
实例(对象)如何由类产生?
我们知道实例是由类产生的,产生过程叫做实例化,那如何产生,语法如下
class Person:
x = 1 #数据属性
def func(self): #函数属性
pass
p = Person() ---> 实例化过程,此时p就是Person的一个实例
一个类可以产生多个实例,比如
class Person:
x = 1 #数据属性
def func(self): #函数属性
pass
p1 = Person()
p2 = Person()
p3 = Person()
每一个实例都是独立,前面我们说到类属性字典,而实例是类产生而来,那么实例也应该有属性字典,没错实例也有自己的属性字典,我们可以访问实例的属性字典,看一看实例的属性字典中存储的是什么值
class Person:
x = 1 #数据属性
def func(self): #函数属性
pass
p = Person()
print(p.__dict__)
打印结果
{}
打印结果为空表明,确实存在实例属性字典,但是x,func并不属于实例的属性,x,func是类属性,它们是归类所有的,所以实例是否可以使用这个属性呢,答案是肯定的
class Person:
x = 1 #数据属性
def func(self): #函数属性
pass
p = Person()
print(p.x)
打印结果
1
print(p.x)是为了去找实例p中x属性,虽然在实例的属性字典中无法找到,但是在类属性字典能够找到,那么就打印,就好比函数的作用域,内层找不到就去外层找。所以当实例去调用某个属性的时候,如果在自己的属性字典中找不到就会去类属性字典中找。
-
实例和类之间的关系
比如我们创建一个中国人的类,首先中国人所共有的属性是国籍中国,所以就把共有的属性放在类属性中。实例是由类产生的,上图中由一个类产生了3个实例,那么每个实例都是一个人,所以每个人都有姓名和年龄对吧,而姓名、年龄就应该是实例属性,存在于每个实例自己的属性字典中,这样实例与实例之间才是互补干扰的,另外,函数speak也是中国人所有共有的动作,那么也是放在类的属性字典中,但是每个实例可以取调用这个函数,那么问题来了我们怎么给实例加上实例自己的属性呢,下面就介绍如何给实例添加属性
-
给实例添加属性(init方法)
实例属性和类属性是独立,但是在访问实例属性时,如果找不到,那么就会去类里面找,现在init方法就是给初始化实例属性的,比如我们有一个需求
1.定义一个类Person,类属性country = “China”
2.生成1个实例,实例要有姓名和年龄
首先定义一个Person类十分简单
class Person:
country = "China"
按照要求我们要给生成一个实例,并且加上年龄和姓名属性
p1=Person()
p1.name="ww"
p1.age=12
此时我们去打印实例属性字典可看到结果
print(p1.__dict__)
结果
{"name":"ww","age":12}
说明我们已经将属性添加到了实例p1上,那么问题来了-->我现在要产生第二个实例,怎么操作,如下:
p2=Person()
p2.name="ww"
p2.age=12
print(p2.__dict__)
当然打印的结果是一样的,但是发现我们在重复的做一件事情就是给实例添加属性,此时如果我们在定义类的时候,实现一个init方法,那么就可以简化操作,具体实现代码如下:
class Person:
country = "China"
def __init__(self,name,age):
self.name=name
self.age=age
init方法接收的第一个参数是self,其实在这里我们已经能够看书self是什么了,就是实例,此时我们在进行是实例化的时候,我们就直接把name 和age传给类
p1 = Person("ww",12) --->自动执行__init__方法,将"ww"传给name,将12传给age
此时我们就可以通过init方法来初始化我们的实例属性,同时我们也可以看到此时实例属性也被添加到自己的属性字典中。