关于私有方法
(1)由于方法和属性本质都是对象,所以私有方法和私有属性的实现机制一样,都是伪私有,即名称重整机制
(2)私有方法的形式也和私有属性一样,即_a()是受保护方法,__a()是私有方法
关于内置特殊方法
(1)信息格式化操作方法__str__():在打印一个实例时,如print(p),解释器会自动去类中寻找__str__()方法的返回值,并将其作为结果打印出来
class Person(object): def __init__(self, n, a): self.name = n self.age = a def __str__(self): return "此人姓名是:%s, 此人年龄是:%d" % (self.name, self.age) p1 = Person("zx", 18) print(p1) p2 = Person("zy", 20) print(p2)
还有一种信息格式化方法是__repr__(),两者的区别是面向的角色不同,前者面向读者,可以展示读者能看懂的东西;后者面向程序员,展示的是该对象的模块、类和存储位置等信息
(2)调用操作方法__call__():类中存在该函数时,其实例可以当作函数来调用,如p(),这时执行方法中的内容,小案例如下:
class penFactory(object): def __init__(self, p_type): self.p_type = p_type def __call__(self, p_color): print("类型是{1},颜色是{0}".format(p_color, self.p_type)) gangbiFunc = penFactory("钢笔") gangbiFunc("红色") gangbiFunc("黄色") gangbiFunc("绿色") gangbiFunc = penFactory("铅笔") gangbiFunc("红色") gangbiFunc("黄色") gangbiFunc("绿色")
上述也案例可以使用偏函数实现,因为其类型较少,而每个类型对应多个颜色,可以使用偏函数来固定类型变量的值
(3)索引操作方法__setitem__(),__getitem__()和__delitem__():使用p[key] = value赋值时执行__setitem__()方法,使用p[key]索引时执行__getitem__()方法,使用del p[key]时执行__delitem__()方法
class Person(object): def __init__(self): self.dict = {} def __setitem__(self, key, value): print("set") self.dict[key] = value def __getitem__(self, item): print("get") return self.dict[item] def __delitem__(self, key): print("del") del self.dict[key] p = Person() p["name"] = "zx" p["age"] = 18 print(p.dict) print(p["name"]) del p["age"] print(p.dict)
切片方法和索引方法是一样的,只是在赋值时,将值赋给切片后的位置
(4)比较操作方法__eq__()、__ne__()、__gt__()、__ge__()、__lt__()、__le__():分别代表==,!=,>,>=,<,<=。对实例对象作比较时,会执行对应的方法内容。需要注意的时,如果只有__gt__()方法,但进行的是小于操作如p1<p2,解释器会自动进行参数调换,即变成p2>p1,据此特性知道,只需要写出大于和等于就可以推出其他的方法,因此可以对代码进行简化:
import functools @functools.total_ordering class Person(object): def __init__(self, age, height): self.age = age self.height = height def __gt__(self, other): print("gt") return self.age > other.age def __eq__(self, other): print("eq") return self.age == other.age p1 = Person(18, 180) p2 = Person(17, 170) p1 >= p2
这里用到一个装饰器,可以将两个方法进行组合,如大于和等于组合为大于等于
(5)遍历操作方法一__getitem__():使用for in对实例进行遍历时,可以执行__getitem__()方法,这里需要在方法中加入结束标识,使遍历到一定条件时停止遍历,因为for in会持续访问实例,每次访问都要执行一次__getitem__()方法,如果没有结束标识,就会是死循环
class Person(object): def __init__(self): self.item = 1 def __getitem__(self, item): self.item += 1 if self.item >= 6: raise StopIteration("停止遍历") else: return self.item p = Person() for i in p: print(i)
其中raise表示抛出异常
(6)遍历操作方法二__iter__()和__next__():这两个方法是同时存在的,前者使实例对象可迭代,后者创建迭代器
class Person(object): def __init__(self): self.item = 1 def __iter__(self): return self def __next__(self): self.item += 1 if self.item >= 6: raise StopIteration("停止遍历") else: return self.item p = Person() import collections print(isinstance(p, collections.Iterable)) for i in p: print(i)
方法一和方法二的区别在于前者的实例对象不可迭代且不是迭代器,后者的实例对象可迭代且是迭代器,这里需要注意的使,迭代器一定可迭代,可迭代不一定使迭代器
(7)迭代器复用:使用面向对象方法生成迭代器时,要使得迭代器可以复用,则可以在__iter__()方法中对迭代器进行回退操作,即对迭代器进行重新赋值,复用时,程序再次执行到__iter__()方法,迭代器被退回原始点
class Person(object): def __init__(self): self.item = 1 def __iter__(self): self.item = 1 return self def __next__(self): self.item += 1 if self.item >= 6: raise StopIteration("停止遍历") else: return self.item p = Person() for i in p: print(i) for i in p: print(i)