对象是模拟真实世界,把数据和程序进行封装 。
对象 = 属性+ 方法
我们需要用类来创造一个对象,就像我们要用图纸来造房子一样。在Python中函数名是以小写字母开头 ,类名是以大写字母开头。
面向对象(Object Oriented)我们一般称为OO,OO的特征有
1、封装
就像我们对列表的操作一样,很多方法已经封装好了,我们只需要调用自己需要的方法的名字就好了
>>> list1 = [2,1,7,4,3]
>>> list1.sort()
>>> list1
[1, 2, 3, 4, 7]
>>> list1.append(9)
>>> list1
[1, 2, 3, 4, 7, 9]
>>>
2、继承
继承是子类自动共享父类之间数据和 方法的机制
>>> class Mylist(list):
pass
>>> list2 = Mylist()
>>> list2.append(5)
>>> list2.append(6)
>>> list2
[5, 6]
>>> list2.append(3)
>>> list2.sort()
>>> list2
[3, 5, 6]
>>>
我们创建的类可以继承列表的很多属性
3、多态
多态就是不同对象对同一方法响应不同的行动
>>> class A:
def fun(self):
print('我是小义')
>>> class B:
def fun(self):
print('我是XX')
>>> a = A()
>>> b = B()
>>> a.fun()
我是小义
>>> b.fun()
我是XX
>>>
我们上面的程序用到了self,但是它 什么东西我们并没有解释,其实它就相当于一个序号
>>> class Ball:
def setname(self,name):
self.name = name
def kick(self):
print('谁踢我%s。。。。。' % self.name)
>>> a = Ball()
>>> a.setname('A')
>>> b = Ball()
>>> b.setname('B')
>>> c= Ball()
>>> c.setname('C')
python的 魔法方法__init__(self)(构造方法):
__init__(self , param1, param2...)
>>> class Ball:
def __init__(self,name):
self.name = name
def kick(self):
print('我叫%s' % self.name)
>>> b = Ball('小义')
>>> b.kick()
我叫小义
>>> a = Ball()
Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
a = Ball()
TypeError: __init__() missing 1 required positional argument: 'name'
>>>
因为我们设置了默认参数如果不传入参数就会报错 。
公有和私有:
公有和私有的意义这里我就不解释了,就是字面意思
默认来说对象的属性和方法都是公有的,为了实现私有Python内部给出了一个name mangling(名字改编,名字重整)的机制
在python中定义私有变量只需要在变量名或函数名前加上‘’__‘’两个下划线,Python所谓的私有只是意义上的,为什么这么说看下面的代码大家就明白了。
>>> class Person:
name = '小义'
>>> p = Person()
>>> p.name
'小义'
>>> class Preson:
__name = '小义'
>>> p = Person()
>>> p.__name
Traceback (most recent call last):
File "<pyshell#65>", line 1, in <module>
p.__name
AttributeError: 'Person' object has no attribute '__name'
>>>
针对上面的代码想打印私有还是可以的,不过要多写一个函数:
>>> class Preson:
__name = '小义'
def getname(self):
return self.__name
>>> p = Preson()
>>> p.getname()
'小义'
>>>
其实我们也可以通过另一种方式:_类名__变量名
>>> class Preson:
__name = '小义'
def getname(self):
return self.__name
>>> p._Preson__name
'小义'
>>>
这里我们在来说一下继承:
被继承者我们 称为基类或父类,继承者我们称为子类,子类可以继承父类的属性和方法。
>>> class Parent:
def hello(self):
print('正在调用父类的方法')
>>> class Child(Parent):
pass
>>> p = Parent()
>>> p.hello()
正在调用父类的方法
>>> c = Child()
>>> c.hello()
正在调用父类的方法
>>> class Child(Parent):
def hello(self):
print('正在调用子类的方法')
>>> c = Child()
>>> c.hello()
正在调用子类的方法
>>> p.hello()
正在调用父类的方法
>>>
在举一个例子说明一下:
import random as r
class Fish:
def __init__(self):
self.x = r.randint(0,10)
self.y = r.randint(0,10)
def move(self):
self.x -= 1
print('我的位置是:',self.x ,self.y)
class Goldfish(Fish):
pass
class Carp(Fish):
pass
class Shark(Fish):
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('饿了,要进食')
self.hungry = False
else:
print('吃饱了')
看一下运行的结果:
>>> fish = Fish()
>>> fish.move()
我的位置是: 2 8
>>> goldfish = Goldfish()
>>> goldfish.move()
我的位置是: 9 0
>>> shark = Shark()
>>> shark.eat()
饿了,要进食
>>> shark.eat()
吃饱了
>>> shark.move()
Traceback (most recent call last):
File "<pyshell#101>", line 1, in <module>
shark.move()
File "D:\Python\test\test.py", line 10, in move
self.x -= 1
AttributeError: 'Shark' object has no attribute 'x'
>>>
从上面的例子运行的结果可以看出,我们在让shark移动的时候莫名其妙的报错了,原因是因为我们从新定义了__init__()所以覆盖掉了父类的方法和属性。针对 这个问题有两种解决的办法:
1、使用未绑定的父类:
import random as r
class Fish:
def __init__(self):
self.x = r.randint(0,10)
self.y = r.randint(0,10)
def move(self):
self.x -= 1
print('我的位置是:',self.x ,self.y)
class Goldfish(Fish):
pass
class Carp(Fish):
pass
class Shark(Fish):
def __init__(self):
Fish.__init__(self)
self.hungry = True
def eat(self):
if self.hungry:
print('饿了,要进食')
self.hungry = False
else:
print('吃饱了')
我们增加了一行代码 :Fish.__init__(self)这行代码中的self已经不是父类的self了,而是子类的self
运行的结果:
>>> shark = Shark()
>>> shark.move()
我的位置是: -1 3
>>>
2、super()
import random as r
class Fish:
def __init__(self):
self.x = r.randint(0,10)
self.y = r.randint(0,10)
def move(self):
self.x -= 1
print('我的位置是:',self.x ,self.y)
class Goldfish(Fish):
pass
class Carp(Fish):
pass
class Shark(Fish):
def __init__(self):
super().__init__()
self.hungry = True
def eat(self):
if self.hungry:
print('饿了,要进食')
self.hungry = False
else:
print('吃饱了')
这种方法是将上一种方法的那一条添加的语句改为: super().__init__()
看一下运行的结果:
>>> shark = Shark()
>>> shark.move()
我的位置是: -1 5
>>>
第二种方法比较简单便捷,所以我们一般情况会用第二种方法。
多重继承:一个子类可以继承多个父类的属性和方法
>>> class Base1:
def fool1(self):
print('我是fool1')
>>> class Base2:
def fool2(self):
print('我是fool2')
>>> class C(Base1,Base2):
pass
>>> c = C()
>>> c.fool1()
我是fool1
>>> c.fool2()
我是fool2
>>>
多继承很容易导致一些不可知的错误,所以一般情况下我们是不使用的。