Python 技能提升(二)

理想的类结构

在这里插入图片描述

@Property装饰器

# 传统写法
class Square1:
    def __init__(self):
        self.__side = None

    def get_side(self):
        return self.__side

    def set_side(self, side):
        assert side >= 0, '边长不能为负数!'
        self.__side = side

    def del_side(self):
        # del self.__side
        self.__side = 0  # 这里并不打算真的去删除


# Pythonic写法
class Square2:
    def __init__(self):
        self.__side = None

    @property
    def side(self):
        return self.__side

    @side.setter
    def side(self, side):
        assert side >= 0, '边长不能为负数!'
        self.__side = side

    @side.deleter
    def side(self):
        # del self.__side
        self.__side = 0  # 这里并不打算真的去删除


s = Square2()
s.side = 10
print(s.side)  # 10
del s.side
print(s.side)  # 0

公有化与私有化

# 在Python类里面,"属性和方法"默认都是公有的(public)
class Person:
    def __init__(self, name: str, age: int):
        self._name = name  # _ 类似与 C++ 的 protected,特点:_name 可以在类内部使用,也可以被继承
        self.__age = age  # __ 类似与 C++ 的 private,特点:__age 可以在类内部使用,但不可以被继承

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

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

    @age.setter
    def age(self, name):
        self.__age = name


class Teacher(Person):  # 继承Person类

    @property
    def info(self):
        return self._name, self.__age  # 报错,不存在 __age 属性


t = Teacher('Jack', 35)
print(t.info)

属性控制

# 属性控制,可用于拦截或日志
class Person:
    # 控制获取属性
    def __getattribute__(self, item):
        print(f'getting attribute [{
     item}]')
        return super().__getattribute__(item)  # 调用父级(object)的方法

    # 控制设置属性
    def __setattr__(self, key, value):
        print(f'setting attribute [{
     key}] to [{
     value}]')
        super().__setattr__(key, value)  # 调用父级(object)的方法


person = Person()
person.name = 'Jack'  # 触发"__setattr__"方法
print(person.name)  # 触发"__getattribute__"方法

"""
运行结果:

setting attribute [name] to [Jack]
getting attribute [name]
Jack

"""

MRO

在这里插入图片描述

"""
MRO: Method Resolution Order(方法解析顺序)
作用:用于类的继承树的方法搜索顺序

在单继承的情况下,我们可以很好的理解"类的继承树的方法顺序"
但是在多继承下,"类的继承树的方法顺序"就显得尤为复杂了(在 Python3 里面,使用了C3线性化的算法进行排序)
通常情况下,我们可以使用类的 mro() 方法来直接查看"类的继承树的方法顺序"
"""


class A(object):
    pass


class B(object):
    pass


class C(object):
    pass


class D(object):
    pass


class E(object):
    pass


class K1(C, A, B):
    pass


class K2(A, D):
    pass


class K3(B, D, E):
    pass


class Z(K1, K2, K3):
    pass


print(Z.mro())
# [
# <class '__main__.Z'>,
# <class '__main__.K1'>,
# <class '__main__.C'>,
# <class '__main__.K2'>,
# <class '__main__.A'>,
# <class '__main__.K3'>,
# <class '__main__.B'>,
# <class '__main__.D'>,
# <class '__main__.E'>,
# <class 'object'>
# ]

可迭代对象

# 利用迭代对象进行迭代,本质是用时间换取空间
# 在迭代进行的那一刻,数据才被产生或处理,从而大幅降低了内存空间的占用

print('\n-----------------------------')

# 可迭代对象的迭代
lst = [66, 77, 88]
for num in lst:
    print(num, end=' ')

print('\n-----------------------------')

# 上面 for 循环的迭代原理如下
iter_obj = lst.__iter__()
print(iter_obj.__next__(), end=' ')
print(iter_obj.__next__(), end=' ')
print(iter_obj.__next__(), end=' ')

print('\n-----------------------------')


# 自定义可迭代对象
class Fibonacci:  # 斐波那契数
    """
    F0 = 0
    F1 = 1
    Fn = Fn-1 + Fn-2 (n >= 2)
    0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ...
    """

    def __init__(self, n):
        self.__n = n
        self.__previous = 0
        self.__current = 1
        self.__count = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.__count >= self.__n:
            raise StopIteration

        self.__count += 1
        return_value = self.__previous
        self.__previous, self.__current = self.__current, self.__previous + self.__current
        return return_value


# 自定义可迭代对象的迭代
for num in Fibonacci(12):
    print(num, end=' ')

print('\n-----------------------------')

"""
运行结果:

-----------------------------
66 77 88 
-----------------------------
66 77 88 
-----------------------------
0 1 1 2 3 5 8 13 21 34 55 89 
-----------------------------

"""

__getitem__()方法

"""
在创建一个可迭代的对象序列时,可以用__iter__()和__next__()方法
如果没有这两个方法,我们还可以通过__getitem__()方法和__len__()方法进行创建序列
如果__getitem__()方法和__len__()方法也没有的话,解释器会抛出 TypeError 的错误!


而__getitem__()方法与上面的__iter__()方法正好相反
它是以空间换取时间:
    1.先占用内存,布置好数据
    2.随机查找的时
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值