Python 类
基本概念介绍
类: 把一类事物的相同的特征和动作整合到一起就是类
对象:基于类而创建的一个具体的事物(具体存在的) 也是特征和动作整合到一起
属性: 1.数据属性:就是变量
2.函数属性:就是函数,在面向对象里通常称为方法
要注意的是 类和对象都用点(.)来访问自己的属性,之后会着重提到这个问题
类的内置系统变量
classname.__name__ 类的名字(字符串)
classname.__doc__ 类的文档字符串(文档是写的注释 单双括号引起来的)
classname.__base__ 类的第一个父类
classname.__bases__ 类的所有父类构成的元组
classname.__dict__ 类的属性字典
classname.__module__ 类定义所在的模块
classname.__class__ 实例化对应的类
类属性增删改
类属性又称为静态变量,或者是静态数据,这些数据是与他们所属的类对象绑定的
class Country: name = 'China' def __init__(self): pass def pas(self): pass Country.name='USA' #改 Country.continent = 'Asia' #增 del Country.pas #删
def eat_food(self,food) pass Chinese.eat = eat_food
这里给Chinese传进去的是eat_food函数的地址,并给它起了个新函数名eat
总的来说,在类中对数据和函数进行修改,实例也会自动修改,在实例中修改数据和新增函数,类不会修改
class Country: name = 'China' pl = Country() print(pl.name) #这里打印的是China Country.name='USA' print(pl.name) #这里打印的是USA
类的底层构成
类和由类构成的模块,它们实际上都是以字典的形式在储存数据
这里用函数来类比类
def school(name, addr, type): def init(name, addr, type): sch = { 'name': name, 'addr': addr, 'type': type, 'kaoshi': kao_shi, #对应的是函数地址 'zhaosheng': zhao_sheng } return sch
def kao_shi(school): #需要传一个字典类型的参数 print("%s 要考试了" % school['name']) def zhao_sheng(school): print("%s 要招生了 " % school['type']) return init(name, addr, type)
就像在上述代码中,类和实例的数据就储存在sch这个字典中,变量数据是直接将值存在字典里,函数是将函数地址放到里面,所以我们可以通过.__dict__这个方法来浏览类的数据,也可以用.dict__[key] = value 来给类和字典新加变量(最好不要这样做)
类和实例的数据和函数属性
类的字典里包括数据和函数两种属性,实例里只有数据属性
当在实例中调用函数时,实际上是要到它所属的类里去找对应的函数。
这就是像在类实例化时,实例把类的数据统统复制到自己这里来,却没有复制它的函数,在调用时如果实例在自己的字典里没有找到要调用的这个数据,就会向自己的上级--类的字典里去找,类里也找不到再报错。(这就像在函数里突然引用到一个没有定义的数据,它会自动向自己的上一级查找一样)
这里的复制我主要是想说实例在遍历字典时有类的所有数据,但事实是在实例化之后类和实例对象的数据也不是相互独立的,就好像在类里有一个自动调用的隐藏函数,每当对类的数据进行修改之后,这个函数会对由这个类实例出来的所有对象一个个重复对这个数据的修改操作(就算在实例里这个数据已经被删除,它也会再加一个新的数据)
class Country:
ss = 't'
pl = Country()
print(pl.__dict__) #这里 ss=t
del pl.ss
print(pl.__dict__) # 字典中已经没有ss了
Country.ss='a'
print(pl.__dict__) # ss加到了字典的最后 并且ss=a
类的__init__和self
类里的__init__是自动调用函数,当你在用类实例化时,第一个(自动)调用的就是这个函数,结合我们上面说的底层字典,我们可以把它的作用看成给新实例创建一个字典,并把相关的数据都放到字典里(已经说了它的字典里没有函数)
class Country: def __init__(self,name,continent): self.name = name self.continent = continent pl = Country('China','Asia') print(pl.__dict__)
类中的self其实就是指实例对象本身 pl,向类里传参数时会自动把实例名作为第一个参数传进去,而 self.name = name 的意思是在实例里加上这样一个参数,就像我在上面的代码中传参China, self.name=name的意思就是在pl这个实例里写name=China这一行代码。
要注意__init__是一个函数,Country的字典里放着这个函数的地址,是没有name和continent这两个数据的。
类和实例的作用关系
前面提到类和实例的底层是字典实现的,那么在生成实例时,用__dict__方法可以看到实例里的变量只有在__init__或其它函数输入的变量,定义类时定义的变量是找不到的,类和实例的关系实际上就像大圆包小圆,类的数据和函数在大圆里,实例的内容在小圆里,在实例调用变量时先在自己的范围里找,找不到再去类里找,还是没有就报错。
class Country: name = 'xiaoming' pl = Country() print(pl.__dict__) #字典中为空 print(pl.name) #打印xiaoming pl.name = 'xiaowang' print(pl.__dict__) #字典中是name=xiaowang print(pl.name) #打印xiaownag
从这段代码可以看到,它并没有向上去类里找到name,修改类里的name,而是直接在实例里新增了一个变量
但值得一提的是,如果是列表的这种追加,就会回到类里修改
class Country: name =['xiaoming','xiangwang'] pl = Country() pl.name.append('xiaosun') #直接追加 print(Country.__dict__) #name列表中多了xiaosun print(pl.__dict__) #空
因为实例只在函数中接受输入的参数,所以它的字典绝大部分时候只有数据,没有函数。
类和实例的调用都是通过 . 来完成,加 . 调用的都是属性,没有 . 就是一个普通变量,和类没有关系了
name = 'xiaoming' class pp: name = 'xiaowang' def prname(self): print(name) pp.prname(None) #这里写个None是给self传值
可以看到打印的是'xiaoming',这就好比你想打印实例pl里的变量name,你应该写print(pl.name),但你直写了print(name),打印出来的内容当然和实例、类一点关系也没有