python面向对象-学习笔记(六、方法相关的补充)

发布时间 2023-10-29 22:14:56作者: 阿慢2010

私有化方法

私有方法
class Person:
    __age = 18

    # 私有方法
    def __run(self):
        print("run")

    # def _Person__run(self):
    #     print("Person run")


p = Person()
# p.__run()
# p._Person__run()

print(Person.__dict__)

image

内置特殊方法

信息格式化操作__str__方法
class Person:
    def __init__(self, n, a):
        self.name = n
        self.age = a
    # 信息格式化
    def __str__(self):
        # s = "name=" + self.name + ";" + "age=" + str(self.age)
        s1 = f"name={self.name};age={self.age}"
        return s1


p1 = Person("sz", 18)
# print(p1.name)
# print(p1.age)
print(p1, type(p1))

p2 = Person("zhangsan", 19)
# print(p2.name)
# print(p2.age)
print(p2)

s = str(p1)
print(s, type(s))

image

信息格式化操作__repr__方法
class Person:
    def __init__(self, n, a):
        self.name = n
        self.age = a

    # def __str__(self):
    #     # s = "name=" + self.name + ";" + "age=" + str(self.age)
    #     s1 = f"name={self.name};age={self.age}"
    #     return s1

    def __repr__(self):
        return "reprxxxxx"


p1 = Person("sz", 18)
# 首先找类内部的__str__方法的返回;没有则找__repr__方法的返回
print(p1, type(p1))

p2 = Person("zhangsan", 19)
print(p2)

print(repr(p1))

image

__str__方法和__repr__方法的区别&联系
import datetime

t = datetime.datetime.now()
print(t)
print(repr(t))

tmp = repr(t)
result = eval(tmp)

print(result)

image

对象像函数一样调用__call__方法
class PenFactory:
    def __init__(self, p_type):
        self.p_type = p_type

    def __call__(self, p_color):
        print("创建了一个%s这个类型的画笔,它是%s颜色" % (self.p_type, p_color))


gangbiF = PenFactory("钢笔")
gangbiF("黄色")
gangbiF("绿色")
gangbiF("蓝色")

qianbiF = PenFactory("铅笔")
qianbiF("黑色")
qianbiF("白色")

image

对象的索引操作__setitem__、__getitem__、__delitem__方法
class Person:
    def __init__(self):
        self.cache = {}

    def __setitem__(self, key, value):
        print("setitem", key, value)
        self.cache[key] = value

    def __getitem__(self, item):
        print("getitem", item)
        return self.cache[item]

    def __delitem__(self, key):
        print("delitem", key)
        del self.cache[key]


p = Person()

p["name"] = "sz"

print(p["name"])

del p["name"]

print(p.cache)
print(p.__dict__)

image

对象的切片操作__setitem__、__getitem__、__delitem__
l = [1, 2, 3, 4, 5]
print(l[3])
print(l[1:4:2])


class Person:

    def __init__(self):
        self.items = [1, 2, 3, 4, 5, 6, 7, 8]

    def __setitem__(self, key, value):
        # print(key, value)
        # print(key.start)
        # print(key.stop)
        # print(key.step)
        # print(value)
        if isinstance(key, slice):
            self.items[key.start:key.stop:key.step] = value

    def __getitem__(self, item):
        print("getitem", item)

    def __delitem__(self, key):
        print("delitem", key)


p = Person()

p[0:4:2] = ["a", "b"]
print(p.items)
p[0:5:2]

image

对象的比较操作__eq__、__ne__、__ge__、__le__、__gt__、__lt__方法
class A:
    def __init__(self, age, height):
        self.age = age
        self.height = height

    # 等于
    def __eq__(self, other):
        # print(other)
        return self.age == other.age

    # 不等于
    def __ne__(self, other):
        print("not equal")

    # # 大于等于
    # def __ge__(self, other):
    #     pass

    # # 大于
    # def __gt__(self, other):
    #     pass

    # # 小于等于
    # def __le__(self, other):
    #     print("__le__")
    #     pass

    # 小于(如果没有__gt__,大于也使用这个方法)
    def __lt__(self, other):
        print("__lt__")
        return self.age < other.age

    pass


a1 = A(18, 180)
a2 = A(19, 190)

print(a1 == a2)
print(a1 != a2)
# print(a1 <= a2)

print(a1 > a2)

image

对象的比较操作补充-装饰器@functools.total_ordering
import functools


# 这个装饰器,可以补全比较操作
@functools.total_ordering
class Person:
    def __lt__(self, other):
        print("lt")
        return False

    def __eq__(self, other):
        print("eq")
        return True


p1 = Person()
p2 = Person()
print(p1 <= p2)
print(Person.__dict__)

image

上下文环境的布尔值 __bool__方法
class Person:
    def __init__(self):
        self.age = 20

    # 可以控制实例真假
    # 如果成年了就打印
    def __bool__(self):
        return self.age >= 18

    pass


p = Person()

# 非空即真
if p:
    print("我成年啦!!!")

image

对象的遍历操作__getitem__方法
class Person:

    def __init__(self):
        self.result = 0

    def __getitem__(self, item):
        self.result += 1
        if self.result >= 6:
            raise StopIteration("停止遍历")
        return self.result

    pass


p = Person()

for i in p:
    print(i)

image

对象的遍历操作__iter__、__next__方法(迭代器对象)
# 实现__iter__方法,可迭代对象
# 同时实现__iter__和__next__方法,迭代器对象
class Person:

    def __init__(self):
        self.items = [1, 2, 3, 4, 5, 6, 7, 8]
        # self.result = 0

    # def __getitem__(self, item):
    #     print("getitem")
    #     self.result += 1
    #     if self.result >= 6:
    #         raise StopIteration("停止遍历")
    #     return self.result

    # 优先级比__getitem__要高
    def __iter__(self):
        print("iter")
        # iter 返回迭代数据
        # return iter(self.items)
        # 需要实现__next__方法才可以
        return self

    def __next__(self):

        if len(self.items) > 0:

            item = self.items.pop()
        else:
            item = None

        if item is None:
            raise StopIteration("已经完成遍历")

        return item
        # self.result += 1
        # if self.result >= 6:
        #     raise StopIteration("停止遍历")
        # return self.result

    pass


p = Person()

# 遍历
for i in p:
    print(i)
# 获取下一个元素
# print(next(p))
# print(next(p))
# print(next(p))
# print(next(p))
# print(next(p))
# print(next(p))
# print(next(p))

image

迭代器对象
class Person:

    def __init__(self):
        self.age = 1

    def __iter__(self):
        # 恢复迭代器初始值
        self.age = 1
        return self

    def __next__(self):
        self.age += 1

        if self.age >= 3:
            raise StopIteration("stop")

        return self.age


p = Person()

for i in p:
    print(i)
print(p.age)

# 判断实例是否是迭代器
# 类需要实现__iter__和__next__两个方法才能使得类的实例为迭代器
import collections.abc

print(isinstance(p, collections.abc.Iterator))
print(isinstance(p, collections.abc.Iterable))

image

Iter函数的使用

class Person:

    def __init__(self):
        self.age = 1

    def __getitem__(self, item):
        self.age += 1
        if self.age >= 6:
            raise StopIteration("停止遍历")
        return self.age

    def __iter__(self):
        self.age = 1
        return self

    def __next__(self):
        self.age += 1

        if self.age >= 4:
            raise StopIteration("stop")

        return self.age

    def __call__(self, *args, **kwargs):
        print('call')
        self.age += 1

        if self.age >= 6:
            raise StopIteration("stop")

        return self.age


p = Person()

# for i in p:
#     print(i)
#
# print(f"当前的p.age值: {p.age}")

# p.age = 1
# pt = iter(p)
# pt = iter(p.__next__(), 4)

pt = iter(p, 4)

# print(pt is p)
#
for i in pt:
    print(i)

print(f"当前的p.age值: {p.age}")

image

描述器property方法
class Person:
    def __init__(self):
        self.__age = 10

    def get_age(self):
        return self.__age

    def set_age(self, value):
        if value < 0:
            value = 0
        self.__age = value

    def del_age(self):
        del self.__age
    
    # 数据描述器
    age = property(get_age, set_age, del_age)


p = Person()
help(p)

image

描述器@property装饰器
class Person:
    def __init__(self):
        self.__age = 10

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, value):
        if value < 0:
            value = 0
        self.__age = value

    @age.deleter
    def age(self):
        del self.__age


p = Person()
help(p)

image

描述器__get__、__set__、__delete__方法
# 描述器只在新式类中生效
class Age:
    def __get__(self, instance, owner):
        print("get")

    def __set__(self, instance, value):
        print("set")

    def __delete__(self, instance):
        print("delete")


class Person:
    age = Age()

# 描述器需要通过实例来操作,不能通过类来操作
p = Person()
p.age = 1
print(p.age)
del p.age

help(p)

image

描述器-调用细节

资料描述器&非资料描述器
覆盖默认的__getattribute__会导致怎么样的结果
实例属性的正常访问顺序

# 描述器只在新式类中生效
# 资料描述器 实现get&set方法
# 非资料描述器 仅仅实现get方法
# 优先级:资料描述器>实例属性>非资料描述器
class Age:
    def __get__(self, instance, owner):
        print("get")

    def __set__(self, instance, value):
        print("set")


    def __delete__(self, instance):
        print("delete")


class Person:
    age = Age()

    def __init__(self):
        # 实例属性的正常访问顺序
        # 1.实例对象自身的__dict__字典
        # 2.对应类的__dict__字典
        # 3.如果有父类,会再往上层的__dict__字典
        # 4.如果没有找到,又定义了__getattr__方法,就会调用这个方法
        self.age = 10

    # 系统默认实现这个方法,则会检测描述器是否实现了__get__方法,如果有就直接调用
    # 如果没有就按照实例属性的正常访问顺序查找
    # def __getattribute__(self, item):
    #     print("getattribute")


p = Person()
# p.age = 1
print(p.age)
print(p.__dict__)

资料描述器>实例属性
image

实例属性>非资料描述器
image

描述器-值的存储问题
# 值需要存储在instance实例中
class Age:
    def __get__(self, instance, owner):
        print("get", self, instance, owner)
        return instance.v

    def __set__(self, instance, value):
        print("set", self, instance, value)
        instance.v = value

    def __delete__(self, instance):
        print("delete")
        del instance.v


class Person:
    age = Age()


p1 = Person()
p1.age = 18
print(p1.__dict__)
# print(p.age)
# del p.age

p2 = Person()
p2.age = 20
print(p2.__dict__)

image

使用类-实现装饰器
# # 装饰器
# def Check(func):
#     def inner():
#         print("登录验证")
#         func()
#
#     return inner


# 类-实现装饰器(功能等同于上面的装饰器)
class Check:
    def __init__(self, func):
        self.f = func

    def __call__(self, *args, **kwargs):
        print("登录验证")
        self.f()


@Check
def fashuoshuo():
    print("fashuoshuo")


# fashuoshuo()

# 可以用装饰器调用,也可以用这个方式调用
# fashuoshuo = Check(fashuoshuo)
fashuoshuo()

image


学习链接: 【Python】零基础入门 面向对象编程(强烈推荐)