标签:美的 解决 案例 由来 重载 解决办法 2.x strong 基本数据
面向对象是软件开发方法。面向对象的概念和应用已经超越了程序设计和软件开发,电影《无间道》的拍摄就用了面向对象的思想。面向对象是一种对现实世界理解和抽象的方法。
那python中的面向对象是什么样的呢?什么是封装,继承,和多态呢?很多同学都觉得面向对象很难以理解,总觉得面向对象非常神秘,今天我们不妨换个角度来学习面向对象。
类
计算机通过数据来表达现实世界里的信息。因为信息是多种多样的有类型的,所以计算机里的数据也是有类型的。所有的编程语言都会有几个内置的基本数据类型,用来表达最常见的几种信息。但是现实世界里的信息类型是无穷无尽的,所以在实际的开发过程中我们为了更完美的表达信息,我们需要自定义新的数据类型。这就是类了。
案例:要表示一个二维空间里的一个点
在数学中用(0,0)表示原点,(x,y)表示一个在原点右侧x单位,上方y单位的点。
在python中,有几种方法可以表达点
用户自定的数据类型也称为类,类的定义如下所示:
# 类的定义 class Point: """表达一个2维空间里的点"""
print(Point)
结果:
<class ‘__main__.Point‘>
class是关键字,Point是这个类的名称,文本内容是解释这个类的用途。我们定义好这个类之后,在后面的代码中,Point代表的就是这个数据类型,代表所有的点。那我们要表示具体的某一个点就需要通过类去创建一个具体的点,也叫新建一个对象,这个过程叫做实例化,对象是这个类的一个实例。创建一个类的对象的语法非常简单,可以把Point这个类名当做函数来调用,如下所示:
p = Point() print(p)
结果:
<__main__.Point object at 0x03097690>
属性
p是类Point的一个实例,p代表一个具体的点,p应该有x,y坐标,我们可以通过赋值给对象的有命名的元素,这些元素就是属性。
p.x = 0 p.y = 0
print(‘(%g, %g)‘ % (p.x, p.y))
结果:
(0, 0)
方法
我们先来看一个案例
定义一个函数,计算一个点到原点的距离
class Point: """表达一个2维空间里的点""" def distance(a): return (a.x**2 + a.y**2)**0.5 p = Point() p.x = 3.0 p.y = 4.0 d = distance(p) print(‘点p到原点的距离是:%g‘ % d)
结果
点p到原点的距离是:5
所有的对象就是一个具体的数据。从上例可以看出,对象可以作为函数的参数,那么也可以作为函数的返回值。在本例中,类定义和接着的函数定义没有明显的关联。但稍加观察,很明显distance函数接收一个Point对象作为参数。这种现象就是方法的由来。一个方法即是和某个特定的类相关联的函数。
方法和函数在语义上是一样的,但在语法上有两个区别。
上面的distance函数转换成方法非常容易,只需要将函数的定义,移入类定义中即可,注意缩进的改变:
class Point: """表达一个2维空间里的点""" def distance(a): return (a.x ** 2 + a.y ** 2) ** 0.5
现在有两种方式调用方法:第一种方式(更少见的)是函数调用语法:
d = Point.distance(p)
Point是类名,distance是方法名称,p作为参数传入
另一种方式(更简洁,更常用)是使用方法调用语法:
d = p.distance()
在这里distance还是表示方法名称,而p是调用这个方法的对象,也称为主体。和一句话中主语用来表示这句话是关于什么东西的一样,方法调用的主体表示这个方法是关于哪个对象的。在方法中,主体会被赋值给第一个形参,所以本例中p被赋值给形参a。依照惯例来,方法的第一个形参通常叫做self,所以distance通常写成这种形式:
class Point: """表达一个2维空间里的点""" def distance(self): return (self.x ** 2 + self.y ** 2) ** 0.5
self代表的是调用这个方法的对象本身。
接下来我们升级这个方法 ,让这个方法可以计算出任意两个点之间的距离
class Point: """表达一个2维空间里的点""" def distance(self, other_point=None): if other_point: return ((self.x-other_point.x) ** 2 + (self.y-other_point.y) ** 2) ** 0.5 else: return (self.x ** 2 + self.y ** 2) ** 0.5 p = Point() p.x = 3.0 p.y = 4.0 p2 = Point() p2.x = 5.2 p2.y = 7.8 d = p.distance(p2) print(‘p和p2之间的距离是%g‘ % d)
结果:
p和p2之间的距离是4.3909
init方法
init方法(initialization的简写,意思是初始化)是一个特殊的方法,当对象初始化时会被调用。它的全名是__init__(两个下划线,接着是init,再接着两个下划线)。每个点在创建的时候就应该具备x,y坐标的属性,因此我们可以给Point类写一个init方法。
class Point: """表达一个2维空间里的点""" def __init__(self, x=0, y=0): self.x = x self.y = y
__init__的形参和属性名称常常是相同的。语句self.x = x 将形参x的值存储为self的一个属性。形参是可选的,所以你不使用任何实参调用Point时,会得到默认值:
p = Point() print(‘(%g, %g)‘ % (p.x, p.y))
运行结果:
(0, 0)
如果提供一个实参,它会覆盖x:
p = Point(1) print(‘(%g, %g)‘ % (p.x, p.y))
运行结果:
(1, 0)
如果提供二个实参,它会覆盖x和y:
p = Point(1, 2) print(‘(%g, %g)‘ % (p.x, p.y))
运行结果:
(1, 2)
__str__方法
__str__方法和__init__类似,是一个特殊方法,它用来返回对象的字符串表达形式。
上面的Point类的对象,我们想打印看看这个对象的x,y坐标的值时,总是要通过字符串拼接的形式,你可能会想,我们写个方法吧:
def print_point(self): print(‘(%g, %g)‘ % (self.x, self.y))
那么下次我直接调用方法就好了。这是一种解决办法。还有一种办法就是编写__str__方法,我们来给Point类写个str方法。
def __str__(self): return ‘(%g, %g)‘ % (self.x, self.y)
当你打印对象时,Python会调用str方法
p = Point(1, 2) print(p)
运行结果
(1, 2)
建议编写一个新类时,开始先写__init__,以便初始化对象,然后会写__str__,以便调试。
操作符重载
通过定义其他的特殊方法,可以为自 定义类型的各种操作符指定行为。例如:如果你为了Point类定义一个__add__方法,则可以在Point对象上使用+操作符。
def __add__(self, other): new_point = Point() new_point.x = self.x + other.x new_point.y = self.y + other.y return new_point
我们来使用它
p = Point(1, 2) p2 = Point(3, 4) print(p+p2)
运行结果:
(4, 6)
当你对Time对象应用+操作符时,Python会调用__add__。当你打印结果时,Python会调用__str__。幕后其实发生了很多事情。修改操作符的行为以便它能够作用于自定义类型,这个过程称为操作符重载。对每一个操作符,Python都提供了一个对应的特殊方法。更多相关,可以参阅Python官方文档。
标签:美的 解决 案例 由来 重载 解决办法 2.x strong 基本数据
原文地址:https://www.cnblogs.com/superwuchaofan/p/9593205.html