python自学日记13——类和方法

python自学日记13——类和方法

1.操作符重载

通过定义其他的特殊方法,你可以为用户定义类型的各种操作符制定行为。例如,如果你为Time类定义一个__add__方法,则可在时间对象上使用+操作符

class Time(object):
    def __init__(self,hour=0,minute=0,second=0):
        self.hour=hour
        self.minute=minute
        self.second=second
    def time_to_int(time):
        minutes=time.hour*60+time.minute
        seconds=minutes*60+time.second
        return seconds
    def increment(self,seconds):
        seconds+=self.time_to_int()
        return int_to_time(seconds)
    def print_time(time):
        print('%.2d:%.2d:%.2d'%(time.hour,time.minute,time.second))
    def is_after(self,other):
        return self.time_to_int()>other.time_to_int()
    def __str__(self):
        return '%.2d:%.2d:%.2d'%(self.hour,self.minute,self.second)
    def __add__(self,other):
        seconds=self.time_to_int()+other.time_to_int()
        return int_to_time(seconds)

#当你对时间对象应用+操作符时,python会调用add,当你打印结果时,python会调用str
#修改操作符的行为以便它能够作用于用户定义的类型,这个过程叫做操作符重载

start=Time(9,45)
duration=Time(1,35)
print(start+duration)

本来两个时间对象是不可以相加的,但是通过定义了add方法,则可以实现两个时间对象相加。

2.基于类型的分发

为Point对象编写一个add方法,可以接受一个对象或者元组,如果第二个操作对象是一个Point方法,则方法应该返回一个新的Point对象,其x坐标是两个操作对象的x坐标的和,y坐标也类似。

如果迭戈操作对象是一个元组,方法则将第一个元素和x坐标相加,将第二个元素和y相加,并返回一个包含相加结果的心Point对象。

首先需要判断传入的第二个参数的类型与第一个参数类型是否一致,这里需要用到内置函数isinstance,接收一个值和一个类对象(当然也可以换成列表、元组等),如果类型相同则返回True,否则返回False.

然后为每一种情况设置一个方法实现上述效果。

class Point(object):
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def print_point(p):
        print('(%g,%g)'%(p.x,p.y))
    def __str__(self):
        return '(%g,%g)'%(self.x,self.y)
    def increment(self,other):
        return (self.x+other[0]),(self.y+other[1])
    def __add__(self,other):
        if isinstance(other,Point):
            return self.add_point(other)
        else:
            return increment(self,other)#这里写错了,应该写成return self.increment(other)
    def add_point(self,other):
        return (self.x+other.x),(self.y+other.y)
blank=Point(1,2)
white=Point(2,3)
print(blank+white)

返回(3,5)结果是对的,返回试一下元组

print(blank+(2,3))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-78-873124d5c067> in <module>
----> 1 print(blank+(2,3))

<ipython-input-74-241285b4e395> in __add__(self, other)
     14             return self.add_point(other)
     15         else:
---> 16             return increment(self,other)
     17     def add_point(self,other):
     18         return (self.x+other.x),(self.y+other.y)

NameError: name 'increment' is not defined

报错显示increment没有被定义,去类里面看了下发现在第二种情况的代码写错了,应该用方法而不是函数,将代码修改后

class Point(object):
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def print_point(p):
        print('(%g,%g)'%(p.x,p.y))
    def __str__(self):
        return '(%g,%g)'%(self.x,self.y)
    def increment(self,other):
        return (self.x+other[0]),(self.y+other[1])
    def __add__(self,other):
        if isinstance(other,Point):
            return self.add_point(other)
        else:
            return self.increment(other)
    def add_point(self,other):
        return (self.x+other.x),(self.y+other.y)

然后还是报同样的错误,按说明明已经修改成功了,应该返回正确的值,但还是报错,这就说到修改class类时需要重启服务器的问题了,判断标准是我把这段代码复制到另一个页面时是正常返回值,在本页面就一直报错,所以重启了jupyter notebook后就显示正常了。我记得在哪里看到修改class是需要重启服务器的。

3.编写一个叫做Kangaroo的类,有如下方法

  1. 一个__init__方法,将属性pouch_contents(口袋中的东西)初始化一个空列表
  2. 一个put_in_pouch方法接收任何类型的对象,并将它添加到pouch_contents中
  3. 一个__str__方法,返回Kangaroo对象以及口袋中的内容的字符串表达形式。

创建两个Kangaroo对象,将它们赋值给kanga和roo,并将roo添加到kanga的口袋中。

class Kangaroo(object):
    def __init__(self,pouch_contents=[]):
        self.pouch_contents=pouch_contents
    def put_in_pouch(self,a):
        self.pouch_contents.append(a)
    def __str__(self):
        return '%s'%self.pouch_contents
kanga=Kangaroo([1])
roo=Kangaroo([2])
kanga.put_in_pouch(roo)
print(kanga)

这是我看到这个问题想到并写出的代码,但是这个里面有个小的问题,初始化时pouch_contents=[]不具有扩展性,如果修改类的话原来写的都会跟着变,所以在查看答案代码中它有把第一个方法做了下调整:

class Kangaroo(object):
    def __init__(self, contents=None):
        if contents == None:
            contents = []
        self.pouch_contents = contents
    def put_in_pouch(self,a):
        self.pouch_contents.append(a)
    def __str__(self):
        return '%s'%self.pouch_contents

将contents带一个默认值,如果不传参数时就按默认值处理,如果传入参数可以按传入参数处理,扩展性会好一些。

然后答案代码将第三个方法也有处理,不过和我的不一样

class Kangaroo(object):
    def __init__(self, contents=None):
        if contents == None:
            contents = []
        self.pouch_contents = contents
    def put_in_pouch(self,a):
        self.pouch_contents.append(a)
    def __str__(self):
        """return a string representation of this Kangaroo and
        the contents of the pouch, with one item per line"""
        t = [ object.__str__(self) + ' with pouch contents:' ]
        for obj in self.pouch_contents:
            s = '    ' + object.__str__(obj)
            t.append(s)
        return '\n'.join(t)

我基本上能理解这个方法,就是对object.__str__(self)有点疑问,暂时还无法理解,上网查了下发现涉及了一些继承的问题,放在后面学了继承之后再回来看看这个问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值