python深入之类的补充(4)

关于私有方法

(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)

猜你喜欢

转载自blog.csdn.net/zx870121209/article/details/81342889