面向对象三大特性: 封装、继承、多态。
python中默认就支持了多态。所以不用关注多态的知识点。我们主要的知识点就放在封装和继承上,封装和继承是基本的知识。
1、创建简单的类和对象。
- 比较简单的类和对象调用。
class foo(): def foo_test(self): print ('This is foo.foo_test') f = foo() f.foo_test() # This is foo.foo_test # 先创建了一个foo类,这个类中只有一个foo_test方法。 # f = foo() 是把foo类实例化成了一个f对象。 # f.foo_test() 是f调用了foo_test方法。这是在执行foo类中的foo_test方法。
- 向类中的普通方法传递参数
class foo(): def foo_test(self,arg): print (arg) f = foo() f.foo_test('test_arg') # test_arg # 向foo_test方法传递arg的参数。
- 搞清楚类中的self是谁
class foo(): def foo_test(self,arg): print (self,arg) f = foo() print (f) f.foo_test('test1') f2 = foo() print (f2) f2.foo_test('rr3r3') # <__main__.foo object at 0x03894110> # <__main__.foo object at 0x03894110> test1 # <__main__.foo object at 0x038941F0> # <__main__.foo object at 0x038941F0> rr3r3 #
在执行 print (f)的时候,时可以看到f这个对象的内存地址的。当f.foo_test('test1')掉用foo_test时,我们在foo_test函数内也打印self。这时的self内存地址和f这个对象的内存地址一致。所以说明self是调用这个方法的对象。
同样的在f2这个对象的内存地址也说明了self。实例化的对象,self就是哪个对象。
2、在类中创建方法
- 构造方法
构造方法就是当实例化一个对象时,就默认执行的方法。
class foo(): def __init__(self): self.test = 'error' print ('internal month') def foo_test(self,arg): print (self.test) print (arg) f = foo() f.test = '123' f.foo_test('arg_') # internal month # error # arg_ # 在实例化foo对象时,这个__init__内部方法是默认执行的。这个init就是构造方法。
在这例子中,当执行f = foo()时,就会执行foo类中的__init__方法。这个__init__方法就是构造方法。
其中f.test是通过对象想类中的方法传递参数。
最后我们调用了foo_test方法,并向他传递了arg_参数。
3、面向对象三大特性 - 封装
- 使用构造方法封装默认参数
class foo(): def __init__(self,name,age,gender): # 把初始化时的,name,age,gender都封装到类中。 self.name = name self.age = age self.gender = gender def show(self,arg): print (self.name,self.age,self.gender,arg) xiaoming = foo('小明','10','男') xiaoming.show('上山去砍柴') xiaoming.show('开车去东北') xiaoming.show('最爱大保健') zhangsan = foo('张三','10','男') zhangsan.show('上山去砍柴') zhangsan.show('开车去东北') zhangsan.show('最爱大保健') # 小明 10 男 上山去砍柴 # 小明 10 男 开车去东北 # 小明 10 男 最爱大保健 # 张三 10 男 上山去砍柴 # 张三 10 男 开车去东北 # 张三 10 男 最爱大保健
在这个例子中,我们就将name,age,gender这些相同的参数通过构造方法封装到了foo这个类中。所以在之后的show中才能直接调用。
4、面向对象三大特性 - 继承
- 最简单的继承
class foo(): def show(self): print ('foo.show') class foo_1(foo): def foo_1_show(self): print ('foo_1.foo_1_show') test_obj = foo_1() test_obj.show()
# foo.show
foo_1这个类在定义的时候就继承了foo类。所以在执行test_obj.show()方法时,执行了父类中的show方法,因为foo_1这个类中没有show方法。
- 在子类中执行父类的方法
class foo(): def show1(self): print ('foo.show1') class foo2(foo): def show_1(self): super(foo2,self).show1() #有两种调用父类中的方法,推荐用这种方法 # foo.show1(self) print ('foo2.show1') test_obj = foo2() test_obj.show_1() # foo.show1 # foo2.show1
- 重写父类中的方法
class foo(): def show(self): print ('foo.show') class foo_1(foo): def foo_1_show(self): print ('foo_1.foo_1_show') def show(self): print ('foo_1.show') test_obj = foo_1() test_obj.show() # foo_1.show
我们在foo_1定义了与父类相同名称的方法,这时父类的方法就不生效了。就会执行子类中的show方法。
- 多继承,对象查找方法时的顺序
首先是当继承了多个父类时,我们要先从左到右的顺序查找。
class f2(): def show(self): print ('f2.show') class f1(f2): def show1(self): print ('f1.show') class ff1(): def show(self): print ('ff1.show') class sun(f1,ff1): pass obj = sun() obj.show() # f2.show
这里说的从左到右的查找顺序是说,在继承的时候class sun(f1,ff1): 。这行代码中f1在ff1左边。
在说一种情况
在这样的继承中查找方法的顺序应该是,先在f1、f2中查找。如果没有在从ff1中查找,如果ff1中也没有再找最后的根f3。
class f3(): def show(self): print ('f3.show') class f2(f3): def show1(self): print ('f2.show') class f1(f2): def show1(self): print ('f1.show') class ff1(f3): def show(self): print ('ff1.show') class sun(f1,ff1): pass obj = sun() obj.show() # ff1.show