python数值比较器_python笔记16(数据处理笔记1)

学习线性代数的时候,想要可视化,但是仅仅是三维坐标系,我都感觉到手画图很不直观。所以这次的python学习,一方面是把之前没学完的学完,另一方面,也是想了解下图形绘制的技术。以下内容和6.00笔记10是重复的,但和之前记录的侧重点不同,这个笔记更加完整(熟练)。

>>> import math

>>> def addPoints(p1,p2):

r = []

r.append(p1[0]+p2[0])

r.append(p1[1]+p2[1])

return r

>>> p = [1,2]

>>> q = [3,1]

>>> r = addPoints(p,q)

>>> print (r)

[4, 3]

这个知识点之前在听课的时候似乎没有记录,但这个实际上可以视为一个向量加法。但这里有一个问题,就是坐标的表示有两种方法,一个是笛卡尔坐标系,就是普通的直角坐标系;另一种是极坐标,那么如何区分这里的两个点的表达是笛卡尔坐标还是极坐标呢?而且,如果是极坐标的形式的话,也就不能用上面这种addPoints方法。

应对这个问题,就需要用class来整合对象和方法,笛卡尔坐标下有对应的向量相加方法,极坐标有它自己的方法。

>>> class cartesianPoint:

pass

>>> cp1 = cartesianPoint()

>>> cp2 = cartesianPoint()

>>> cp1

cp1 and cp2 are both instances of this type.

>>> cp1.x = 1.0

>>> cp1.y = 2.0

>>> cp2.x = 1.0

>>> cp2.y = 2.0

>>> cp1.x

1.0

cp1 points to an instance, and I have now given an internal variable name

and a value.

以下是判断两个坐标是否重合:

>>> def samePoint(p1,p2):

return (p1.x == p2.x) and (p1.y == p2.y)

>>> samePoint(cp1,cp2)

True

但是不能用python内置比较器结果是这样的:

>>> 4 is 4

True

>>> cp1 is cp2

False

这个称为shallow equality(也称为object equality), 它测试的是:Do these things point to exactly the same spot in memory, the same instance. 前面的称为deep equality(也称为value equality),这个是我们可以自己定义的。

同样的思路可以应用于极坐标。

>>> class polarPoint():

pass

>>> pp1 = polarPoint()

>>> pp2 = polarPoint()

>>> pp1.radius = 1.0

>>> pp1.angle = 0

>>> pp2.radius = 2.0

>>> pp2.angle = math.pi / 4.0

但如果用samePoint()方法来判断极坐标,会出现错误:

>>> samePoint(pp1,pp2)

Traceback (most recent call last):

File "", line 1, in

samePoint(pp1,pp2)

File "", line 2, in samePoint

return (p1.x == p2.x) and (p1.y == p2.y)

AttributeError: 'polarPoint' object has no attribute 'x'

也就是说,虽然坐标的表现形式有极坐标和笛卡尔坐标两种,但本质上都是相同的,不同的只是表现形式。但如果要判定两种坐标是否重合时,竟然要需要两个method来判定。这不科学。而class还可以进一步整合。

class cPoint:

def __init__(self, x, y):

self.x = x

self.y = y

self.radius = math.sqrt(self.x * self.x + self.y * self.y)

self.angle = math.atan2(self.y, self.x)

def cartesian(self):

return (self.x, self.y)

def polar(self):

return (self.radius, self.angle)

def __str__(self):

return '[' + str(self.x) + ',' + str(self.y) + ']'

def __cmp__(self,other):

return (self.x > other.x) and (self.y > other.y)

注意,在cPoint类里面,极坐标是从笛卡尔坐标转化来的。

>>> p = cPoint(1.0, 2.0)

>>> p.x

1.0

>>> p.cartesian()

(1.0, 2.0)

尽管我们可以通过

命令直接获取数值,但是这个方法会让数据“exposed”,数据暴露的问题在于,你不仅可以直接获取数据,也可以修改数据,比如:

>>> p.x = 'foobo'

>>> p.x

'foobo'

为了防止这种情况,需要data hiding。所谓data hiding,就是:One can only access instance values through defined methods. 但python没有提供这种获取数据的限制,因此需要自我约束。以下是另一种“放飞”及后果:

>>> p = cPoint(1.0, 2.0)

>>> p.polar()

(2.23606797749979, 1.1071487177940904)

>>> p.radius = 5.0

>>> p.polar()

(5.0, 1.1071487177940904)

>>> p.cartesian()

(1.0, 2.0)

对__str__的说明:

>>> p

>>> print (p)

[1.0,2.0]

如果把cPoint类中的__str__删除:

>>> class cPoint:

def __init__(self, x, y): # create instances

self.x = x

self.y = y

self.radius = math.sqrt(self.x * self.x + self.y * self.y)

self.angle = math.atan2(self.y, self.x)

def cartesian(self):

return (self.x, self.y)

def polar(self):

return (self.radius, self.angle)

def __cmp__(self,other):

return (self.x > other.x) and (self.y > other.y)

>>> p = cPoint(1.0, 2.0)

>>> print (p)

显然,如果你要打印实例时,python首先自动搜寻__str__方法,如果有,调用该方法。

最后注意如何调用__cmp__方法,首先是错误的:

>>> p.__cmp__(p,q)

Traceback (most recent call last):

File "", line 1, in

p.__cmp__(p,q)

TypeError: __cmp__() takes 2 positional arguments but 3 were given

正确的:

>>> p.__cmp__(q)

False

还有公开课可以但我的python 3不可以的方法:

>>> p>q

Traceback (most recent call last):

File "", line 1, in

p>q

TypeError: '>' not supported between instances of 'cPoint' and 'cPoint'

判定两个坐标是否重合,需要用__eq__方法。关于这些比较方法,在6.00笔记11中有说明。

线段:

>>> class Segment:

def __init__(self, start,end):

self.start = start

self.end = end

def length(self):

return math.sqrt( ((self.start.x - self.end.x) *

(self.start.x - self.end.x)) +

((self.start.y - self.end.y) *

(self.start.y - self.end.y)) )

要注意的是,start, end are actually points。也就是说,在这个Segment类中,its elements are themselves instances of cPoint.

>>> p1 = cPoint(3.0, 4.0)

>>> p2 = cPoint(5.0, 7.0)

>>> s = Segment(p1, p2)

>>> print (s.length())

3.605551275463989

但是这个代码存在一个问题,就是直接读取数据,而不是通过method获取数据。这种data exposing的问题在于,当你的代码数量庞大的时候,有的时候修改会很麻烦。而通过method访问数据的话,那么需要调整的代码量就会少很多,而且明确。关于这点,老师一直在强调“模块化”这个概念。

另外,就这节课内容而言,还有一个封装的概念。我们首先把“点”对应的笛卡尔坐标和极坐标还有相应的方法封装在cPoint里面。在这个基础上,我们可以建立”线段“。之后我们还可以继续延伸,比如建造多边形等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值