1,在python当中一切皆对象,每产生一个对象会对应三个属性:id、类型type和数值
2,创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性:而类中有两种属性:数据属性和函数属性,其中类的数据属性是共享给所有对象的,而类的函数属性是绑定到所有对象的。 3,在类的内部来说,__init__是类的函数属性,但是对于对象来说,就是绑定方法。
4,命名空间的问题:先从对象的命名空间找,随后在从类的命名空间找,随后在从父类的命名
空间找。
5,所谓初始化构造函数就是在构造对象的同时被对象自动调用,完成对事物的初始化,一个类只要生成一个类对象,它一定会调用初始化构造函数.
特点:
1>一个类中只能有一个初始化构造函数
2>不能有返回值
3>可以用它来为每个实例定制自己的特征
6,方法重写指在子类中重新定义父类中已有的方法,这中现象叫做方法的重写
举例
#!/usr/bin/python
# -*- coding:utf-8 -*-
class People:
def __init__(self,name,age):
self.name = name
self.age = age
self.tell()
def tell(self):
print("%s---%s"%(self.name,self.age))
class Student(People):
def tell(self):
print("呵呵!")
if __name__ == '__main__':
student = Student("alex",20)
#查看Student所有的父类
print(Student.__bases__)
#查看最近的父类
print(Student.__base__)
#student既是Student类,又是People类
print(isinstance(student,Student))
print(isinstance(student,People))
运行结果
呵呵!
(<class '__main__.People'>,)
<class '__main__.People'>
True
True
Process finished with exit code 0
在此例中,子类Student和父类People都定义了Tell方法,子类没有定义构造函数,此时调用的是父类的构造函数,但注意父类构造函数在调用tell()方法时,调用的是子类的tell()函数,因为两个函数重名,相当于重写了父类的函数,此时要调用子类重写后的函数。
7,super关键字产生的原因:在子类当中可以通过使用super关键字来调用父类的中相应的方法,简化代码。
使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表。
示例代码:
#!/usr/bin/python
# -*- coding:utf-8 -*-
class Foo:
def test(self):
print("from foo")
class Bar(Foo):
def test(self):
#Foo.test(self)
super().test()
print("bar")
if __name__ == '__main__':
bb = Bar()
bb.test()
运行结果:
from foo
bar
Process finished with exit code 0
8,类变量的可变属性
假如类命名空间中的变量是可变的话,这时候会发生什么呢?
答案是,如果通过类的实例改变了变量,类变量也会发生改变,还是举个例子看看吧
class Service(object):
data = []
def __init__(self, other_data):
self.other_data = other_data
在上面的代码中,在Service的命名空间中定义一个data,其初始值为空list,现在通过对象来改变它
s1 = Service(['a', 'b'])
s2 = Service(['c', 'd'])
s1.data.append(1)
s1.data
## [1]
s2.data
## [1]
s2.data.append(2)
s1.data
## [1, 2]
s2.data
可以看到,如果属性是可变的,在对象中改变这个属性,将会影响到类的命名空间。
可以通过赋值防止对象改变类变量。
s1 = Service(['a', 'b'])
s2 = Service(['c', 'd'])
s1.data = [1]
s2.data = [2]
s1.data
## [1]
s2.data
## [2]
Service.data
[1,2]
在Service类里定义了一个类变量data,注意当我们执行s1.data.append(1)时,对这个类变量进行了修改,增加了一个1.而当我们执行s1.data = [1]时,我们并没有更改类变量data,而是给s1增加了一个变量data,原来的类变量不受影响,Service.data依旧是[1,2]。这一点要特别注意。append和赋值是两种完全不同的操作。实例无法修改类变量的指向,但可以修改类变量指向的内容,注意修改类变量的指向和修改类变量指向的内容是不同的概念。