Python是一个面向对象的编程语言,但是很多人就要问了,到底什么叫做面向对象呢?面向对象编程又是什么呢?
在日常生活中,我们总是喜欢把事物归类,俗话说的好,“物以类聚,人以群分“嘛,我们人类和家里养的猫猫狗狗和大陆两旁的行道树都属于生物类,我们还可以分的更细,人类和猫狗都属于动物类,你我都是人类......
你们肯定也已经发现了,我们之所以这么分类,是因为这些被我们归为一类的事物都有一些共性,所以他们才成为一类,然而在这些共性之外,我们又有许多各自的特点,这也就对应这我们面向对象编程中所讲的多态(多态的概念在后面涉及)
我们今天要讲的Python也是这样,把具有相同属性和方法的对象抽象在一起,也就是我们所说的类
Python的类就像一个模具,是始终不变的,但是如果往里面倒的东西不一样,那么出来的东西虽然形状一样,但是说到底还是有区别的
那么话不多说,开始吧
1、类和对象
在python中定义一个类
在python中定义一个类,基本的语句结构是
class 类名:
属性
方法
注意事项:类名首字母需要大写
下面来一个例子
#在python中定义一个类
class People:
pass
如上定义了一个简单的类People,然后紧接着是一个空语句,表示什么都不执行
在python定义了一个类之后,我们就可以根据这个类来创建对象
#根据类来创建对象
一般格式:
对象名=类()
这样一来,我们就定义好了一个对象
2、属性
属性是每一个对象的特征,对象之间的属性可以相同,但是属性值却可以不同,属性值不必要完全相同
就如同每个人都长了头发,但是有些人头发是黑的,有些人头发是黄的,而有些人却没有头发......
在python中给对象来定义属性的基本方法是:
对象名.属性名=属性值
people.colcor="red"
3、方法
前面说到的属性是一种静态的特征,每个对象都有一些动态的特征,比如学生每天都要上学,父母每天都要上班,python中,用方法来描述对象之间这样的一个动态的特征,下面来简单地定义一个方法
class Student:
def stu_act(self):
print("学生要去上课")
上面给Student类定义了一个简单的stu_act()的方法,要想调用这个方法也很简单,只需要对象名.方法名()即可
stu_one=Student()
stu_one.stu_act() #调用stu_act()方法
构造方法
在python中我们可以用构造方法来初始化类的属性
class Car:
def __init__(self):
self.color="Black" #使用构造方法来初始化Car类的color属性
"""
注意事项:
构造方法里init是被双下划线包围的
"""
我们也可以给__init__()方法传入参数
class Car:
def __init__(self,color):
self.color=color
需要注意的是,当对象调用__init__()方法时,python会自动把对象传给第一个参数self
析构方法
当创建一个对象时,python解释器会默认调用__init__()方法,当删除一个对象时,python解释器会默认调用__del__()方法
class Car:
def __del__(self):
print("正在清除......")
car=Car
del car
print("----------1----------")
#打印结果
正在清除......
__________1__________
如上面代码所示,car对象在使用del,会默认调用__del__()方法,于是先执行我们提前定义好的__del__()方法
4、运算符重载
python中,我们可以很简单地使用加减乘除运算
>>> 1+1
2
>>> 2*5
10
其实在进行加法"+"运算时,python自动调用了__add__()的方法 ,这里我们对python里的加法运算进行重载
__add__()方法有两个参数,一个self,一个other,当一个对象调用加法运算符时,会自动检查该对象是否有__add__方法,如果有,则调用,other参数用来调用后面的那个数
class Add(int):
def __add__(self,another):
return int.__sub__(self,another)
a=Add(5)
b=Add(8)
a+b
-3
class Demo:
def __init__(self,obj):
self.data=obj[:]
def __add__(self,obj):
x=len(self.data)
y=len(obj.data)
max=x if x>y else y
number_list=[]
for n in range(max):
number_list.append(self.data[n]+obj.data[n])
return Demo(number_list[:])
demo=Demo([1,2,3])
demo_two=Demo([10,20,30])
demo_sum=demo+demo_two
print(demo_sum.data)
上面为加法运算符重载的两种实现方法(找一下这两种方法的区别)
>>> class Add:
def __init__(self,num):
self.num=num
def __add__(self,another):
return self.num*another.num
>>> a=Add(2)
>>> b=Add(5)
>>> a+b #将加法重载为乘法!
10
其实上面所演示的都是python里面的一些关于算术运算符的魔法方法的重载,下面再来举几个例子
>>> class New_int(int): #参数int用于接收参数,也可以继承int类
#加法重载为乘法
def __sub__(self,other):
return int.__pow__(self,other)
>>> a=New_int(2)
>>> b=New_int(3)
>>> a-b
8
注意:进行运算符重载时,经常会产生如下的错误
>>> class Try_int(int):
def __sub__(self,other):
return self - other
>>> a=Try_int(4)
>>> b=Try_int(5)
a-b #会产生递归错误
"""
产生递归的原因是__sub__方法返回的是两个Try_int对象的差
而在函数中重载了差运算,程序会不断地执行同一部
直到递归超过最大深度
"""
解决方案是将返回值里面的两个对象转换为int类的数值
>>> class Try_int(int):
def __sub__(self,other):
return int(self) - int(other)
>>> a=Try_int(4)
>>> b=Try_int(5)
a-b
9
前面说到了python调用运算符的顺序,当出现a+b时,Python会自动检查a是否有__add__()方法,如果有,则按照该方法进行运算,如果没有则检查b是否有__radd__()方法,__radd__()方法是__add__方法的反运算符
现在就来简单说一下反运算符吧,还是以加法为例
>>> class Nint(int):
def __radd__(self,other): #重载反运算符方法
return int.__sub__(self,other)
>>> a=Nint(4)
>>> 2+a #由于2没有__add__方法,所以python会检查a的反运算方法,并执行
2
定制对象的字符串形式
在python中,我们可以使用__str__(),和__repr__()方法来定制对象返回的字符串形式,但是这两个方法有区别
>>> class A:
def __str__(self):
return "............."
>>> a=A()
>>> a
<__main__.A object at 0x7fe515b869b0> #无法使用对象名来得到字符串
>>> print(a)
.............
str(a)
'.............'
#只重载__str__()方法的话,只有str和print函数可以调用此方法
>>> class B:
def __repr__(self):
return ""
>>> a=B()
>>> a
>>> print(a)
repr(a)
#重载rper方法可以在任何操作下得到自己自定义的字符串
>>> class C:
def __str__(self):
return "I Love Python"
def __repr__(self):
return "NO I HATE YOU" #同时重载两个方法
>>> a=C()
>>> print(c)
>>> print(a)
I Love Python
>>> repr(a)
'NO I HATE YOU'
>>> str(a)
'I Love Python'
>>> a
NO I HATE YOU
>>>
"""
同时重载两个方法时,只有repr(),print(repr())函数调用repr方法,print,str函数调用str方法
"""