基础概念:
类的定义:
//定义类的一般形式
class Student(object):
...
//class声明这是一个类,类名一般都用大写字母开头,括号里面表示该类从哪里继承来的(父类),如果没有
合适的继承类,就使用object类,这是所有类最终都会继承的类。缩进语句块里面用来声明该类的各种数据和
functions
//实例代码
>>> class Student(object):
... Readline internal error
Traceback (most recent call last):
...
^
IndentationError: expected an indented block //报错?缩进用个Tab不行吗?
>>> class Student(object):
... pass //要一个空格缩进?
...
>>> Student() //通过类名+()就创建出了一个类实例对象
<__main__.Student object at 0x0000024713B0AF60>
>>> instance = Student()
>>> instance //可以发现它是一个Student 类的 object
<__main__.Student object at 0x0000024713B0AE10>
>>> Student //但Student才并且仍是Student类
>>> instance.name = 'yo' //此时我们就可以给实例变量自由的添加属性
>>> instance.name //但是添加的属性不会对类产生任何影响
'yo'
//但是我们可以在创建类的时候,提前定义好一些该类的每一个实例对象都该拥有的属性。
//通过定义一个特殊的__init__方法,在创建实例的时候,把name,age等属性绑上去:
>>> class Student(object):
... def __init__(self,name,age):
... self.name = name
... self.age = age //我python的缩进是不是弄错了。。
...
//进入虚拟环境再用python缩进就正常了,代码好看多了。
>>> class Student(object):
... def __init__(self,name,age): //__init__方法的第一个参数永远是self,表示创建的实例本身
... self.name = name //下面的就表示类自身(Student)的一些属性
... self.age = age
...
>>> instance = Student() //重新定义的类如果还不传参数就会报错
Traceback (most recent call last):
File "", line 1, in
TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
>>> instance = Student(name='ocean',age=19) //实例化的时候self不需要传入
>>> instance = Student('ocean',19) //传入参数的方法和用函数一样,有多种方式
>>> instance.name
'ocean'
>>> instance.age
19
>>> instance.score = 99.9 //此时,除了必须的,同样可以添加“个性化属性"
>>> class Student(object):
... def __init__(self): // __init__() 特殊方法(构造方法),该方法在类实例化时会自动调用
... print(666)
...
>>> yo = Student()
666
>>> class Student(object):
... def __init__(self):
... print(self) //一直不知道这个self表示的是什么,不如看看。
...
>>> yo = Student()
<__main__.Student object at 0x000001E1E2C9F188>
>>> Student //可以看出,self表示的是类实例化后的yo,而不是Student类
OMG,我居然也可以 ,温柔。 --19.8.17
//在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。
//这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:
>>> class Student(object):
... def __init__(self,name,age):
... self.name = name
... self.age = age
... def print(self,score): //封装数据的函数,self是必要的一个参数!
... print("name:%s age:%s"%(self.name,self.age))
... print("score = %s"%(score))
...
>>> instance = Student('ocean',19)
>>> instance.print(99.9)
name:ocean age:19
score = 99.9
//事实上,封装做的就是在类的内部定义函数,从而能够在类的内部对数据进行
处理,我们在外部只需要传入必要的参数,类在内部加工数据,传出我们想要的
结果,而不需要再外部设置函数如此以来使得类变得powerful
//在定义一个class的时候,我们可以从现有的某个已经存在了的类继承,被继承的类被称为父类或者基类(还
是很形象的),产生新的class被称为子类。(之前一直用的object被称为根类)
//上代码
>>> class Animal():
... def printf(self):
... print("This is a Animal")
...
>>> ins0 = Animal()
>>> ins0.printf()
This is a Animal
>>> class Dog(Animal): //定义一个Dog类,继承自Animal类
... pass
...
>>> ins1 = Dog()
>>> ins1.printf() //调用继承自父类方法,看来只是原封不动的搬了过来
This is a Animal
>>> class Cat(Animal): //定义一个 Cat 类,继承自Animal类
... def printf(self): //在子类中重写printf()方法
... print("This is a cat.")
...
>>> ins2 = Cat()
>>> ins2.printf() //调用继承自父类方法,可以发现子类重写的方法成功的将原方法覆盖掉
This is a cat.
//上代码
>>> class Student():
... def __init__(self,age):
... self.age = age
... print(age)
...
>>> yo = Student(19)
19
>>> class Colleage_stu(Student):
... def __init__(self,age,score):
... print(age)
... print(score)
...
>>> ocean = Colleage_stu(19,99) //成功的覆盖掉了构造方法(__init__)
19
99
>>> class Colleage_stu(Student):
... def __init__(self,age,score):
... Student.__init__(self,age) //继承Student类的self和age方法
... self.score = score //添加
自己的方法score
... print(score)
...
>>> ocean = Colleage_stu(19,99) //成功习得自己的方法score
19
99
>>> class Colleage_stu(Student):
... def __init__(self,age,score):
... print(score)
... Student.__init__(self,age)
... print(age)
...
>>> ocean = Colleage_stu(19,99) //基本上可以为所欲为
99
19
19
>>> class Colleage_stu(Student):
... def __init__(self,age,score):
... Student.__init__(self,age,score) //只要不缺心眼的继承一个父类没有的属性
... print(score)
...
>>> ocean = Colleage_stu(19,99)
Traceback (most recent call last):
File "", line 1, in
File "", line 3, in __init__
TypeError: __init__() takes 2 positional arguments but 3 were given
//所谓多继承,就是继承自多个父类白,啧啧啧~
>>> class Teacher():
... def __init__(self,class): //敲了好几遍才意识到这个class还不能用。讲究~
File "", line 2
def __init__(self,class):
^
SyntaxError: invalid syntax
>>> class Teacher():
... def __init__(self,grade): //换了grade就ok了
... print(grade)
...
>>> class Student():
... def __init__(self,age):
... print(age)
...
>>> stu = Student(19)
19
>>> tec = Teacher(10) //验证了一下没毛病
>>> class School(Teacher,Student):
... def __init__(self,grade,age,name):
... print(name)
... Student.__init__(self,age)
... print(age*10)
... Teacher.__init__(self,grade)
... print(grade*10)
...
>>> Tsinghua = School(10,19,"ocean") //还是只要别继承父类没有的属性就可以为所欲为
ocean
19
190
10
100
//上代码
>>> type(Cat)
>>> type(ins2)
//ins2是Cat类型的数据
>>> type(ins0)
//ins0是Animal类型的数据
>>> isinstance(ins2,Cat) //ins2属于Cat类,of course
True
>>> isinstance(ins0,Animal) //ins0属于Animal类,of course
True
>>> isinstance(ins2,Animal) //ins2同样属于Animal类!它继承自父类。
True //这就是所谓的多态
>>> def run_twice(animal): //此函数接受一个Animal类型的变量
... animal.printf()
... animal.printf()
...
>>> run_twice(Animal()) //运行成功,但是为什么定义的时候接受的类名是小写?
This is a Animal
This is a Animal
>>> def run_twice(Animal): //大写是可以的
... Animal.printf()
... Animal.printf()
...
>>> run_twice(Animal())
This is a Animal
This is a Animal
>>> run_twice(Dog()) //我们定义的时候没有定义Dog类,但是他是继承自Animal的,具有多态
This is a Animal
This is a Animal
>>> run_twice(Cat())
This is a cat.
This is a cat.
//由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的
run()方法,这就是多态的意思:
//对于一个变量,我们只需要知道它的父类,而不需要确切的知道子类的内部结果,就可以通过调用父类的方法
来调用子类的相对应的方法。
//这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方
法编写正确,不用管原来的代码是如何调用的。
>>> class Animal():
... def printf(self):
... print("This is a animal.")
...
>>> class Dog(Animal):
... pass
...
>>> class Cat(Animal):
... def printf(self):
... print("This is a cat.")
...
>>> def run(Cat):
... Cat.printf()
...
>>> run(Cat())
This is a cat.
>>> run(Animal())
This is a animal.
>>> run(Dog()) //我都凌乱了,run函数定义的是Cat类,怎么会和Dog类还有父类产生关系?
This is a animal.
>>> ins0 = Animal()
>>> ins2 = Cat()
>>> isinstance(ins0,Cat)
False