关于私有方法
- 由于方法和属性本质都是对象,所以私有方法和私有属性的实现机制一样,都是伪私有,即名称重整机制
- 私有方法的形式也和私有属性一样,即_a()是受保护方法,__a()是私有方法
关于内置特殊方法
- 信息格式化操作方法__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__(),两者的区别是面向的角色不同,前者面向读者,可以展示读者能看懂的东西;后者面向程序员,展示的是该对象的模块、类和存储位置等信息
- 调用操作方法__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("绿色")
上述也案例可以使用偏函数实现,因为其类型较少,而每个类型对应多个颜色,可以使用偏函数来固定类型变量的值
- 索引操作方法__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)
切片方法和索引方法是一样的,只是在赋值时,将值赋给切片后的位置
- 比较操作方法__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
这里用到一个装饰器,可以将两个方法进行组合,如大于和等于组合为大于等于
- 遍历操作方法一__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表示抛出异常
- 遍历操作方法二__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)
方法一和方法二的区别在于前者的实例对象不可迭代且不是迭代器,后者的实例对象可迭代且是迭代器,这里需要注意的使,迭代器一定可迭代,可迭代不一定使迭代器
- 迭代器复用:使用面向对象方法生成迭代器时,要使得迭代器可以复用,则可以在__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)