python 魔法方法

#魔法方法:方法名称前后都会加上两条下划线。如果对象实现了魔法方法,则这个方法会在特定情况下被python调用,完全没有直接调用的必要
#1. 构造方法:__init__() ,当一个对象被创建后,会立即调用构造方法,而无需显示声明
class FooBar:
    def __init__(self, value=42):
        self.somevar = value
foo = FooBar()
foo.somevar #42
foo = FooBar('I want a job')
foo.somevar #'I want a job'
#如果一个类的构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不会被正确的初始化
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print('Aaaah')
            self.hungry = False
        else:
            print('No, thanks!')
class SongBird(Bird):
    def __init__(self):
        self.sound = 'Squawk'
    def sing(self):
        print(self.sound)
sb = SongBird()
sb.eat() #报错:由于self.hungry未被初始化,所以报错
#超类构造方法的调用方式有2种:
#way1:调用未绑定的超类构造方法:该种方法直接调用超类的构造方法,不会有实例被绑定,因而,可以自由提供需要的self参数
class SongBird(Bird):
    def __init__(self):
        Bird.__init__(self) #调用未绑定的超类构造方法
        self.sound = 'Squawk!'
    def sing(self):
        print(self.sound)
sb = SongBird()
sb.eat() #'Aaaah'
sb.eat() #'No, thanks!'
#way2:使用super函数调用超类构造方法,超类__init__()能以绑定的方式被调用。注意:super()只能在新式类中使用。
#使用python2时,需要在定义类前,加语句:__metaclass__ = type;或者,将object子类化:calss Newstyle(object);
#使用python3,object会被默认子类化,因此,无需特殊声明;
#如果超类有多个,way1需要多次调用不同超类构造方法,而super()可以解决这种问题,且不容易产生混乱,因而较way1,是一个better choice!
class SongBird(Bird):
    def __init__(self):
        super(SongBird, self).__init__()
        self.sound = 'Squawk'
    def sing(self):
        print(self.sound)
sb = SongBird()
sb.eat() #'Aaaah'
sb.eat() #'No, thanks'
#基本的序列和映射的实现,需要使用的魔法方法
__len__(self) #可以用len(对象实例)的方式得到对象实例的长度
__getitem__(self, key) #可以通过key得到对象实例相应的value
__setitem__(self, key, value) #可以给对象实例添加一个 键值对
__delitem__(self, key) #可以删除对象实例的一个元素
def checkIndex(key):
    if not isinstance(key, int): raise TypeError
    if key < 0: raise IndexError
class ArithmeticSequence:
    def __init__(self, start=0, step=1):
        self.start = start
        self.step = step
        self.changed = {}
    def __getitem__(self, key):
        checkIndex(key)
        try:return self.changed[key]
        except KeyError:
            return self.start + key * self.step
    def __setitem__(self, key, value):
        checkIndex(key)
        self.changed[key] = value
    def __len__(self):
        return len(self.changed.keys())
    def __delitem__(self, key):
        del self.changed[key]
s = ArithmeticSequence(1,2)
s[4] #9   __getitem__(self,key)
s[4] = 2  # __setitem__(self, key, value)  设定一对 键值对
s[4] #2
s[-4] #IndexError    
len(s) #1  
del s[4] #删除 s[4]  
#__str__将对象实例 以 str 的方式呈现给客户, __repr__将对象实例 呈现在解释器上,无需print(object)
__str__(self) #str()
__repr__(self) #repr()
#添加__str__(self)方法,可以通过print的方式,打印对象实例
class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __str__(self):
        return "Person: %s, %s" % (self.name, self.gender)
p = Person('Bob', 'male')
p #返回其所属类
print(p) #"Person: Bob, male"
#添加__repr__(self)方法,可以直接 将对象实例 呈现于解释器上
class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __repr__(self):
        return "Person: %s, %s" % (self.name, self.gender)
p = Person('Bob', 'male')
p #"Person: Bob, male"
#可以通过 __repr__ = __str__ 的方式,直接重写/定义 __repr__方法    
class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def __str__(self):
        return "Person: %s, %s" % (self.name, self.gender)
    __repr__ = __str__  
p = Person('Bob', 'male')
p #"Person: Bob, male"  
#子类化列表,字典 和 字符串:如果想要实现的类和这些内建类 较为相似,可以直接将这些内建类 子类化
#带有访问计数的列表:如果想在list的基础上,每当元素被访问一次时,则计数一次
class CounterList(list):
    def __init__(self, *arg):
        super(CounterList, self).__init__(*arg)
        self.counter = 0
    def __getitem__(self, key):
        self.counter += 1
        return super(CounterList, self).__getitem__(key)
c = CounterList(range(10))
c # [0,1,2,3,4,5,6,7,8,9]
len(c) #10
c.counter #0
c[4]+c[5] 
c.counter #2        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sarah ฅʕ•̫͡•ʔฅ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值