类与对象深度问题与解决技巧(1如何派生内置不可变类型并修改其实例化行为)

如何派生内置不可变类型并修改其实例化行为

我们想自定义一种新类型的元组,对于传入的可迭代对象,我们只保留其中int类型且值大于0的元素,例如:
IntTuple([2,-2,‘jr’,[‘x’,‘y’],4]) => (2,4)
如何继承内置tuple 实现IntTuple?

如果直接在init中进行修改

class IntTuple(tuple):
    def __init__(self, iterable):
        for i in iterable:
            if isinstance(i, int) and i > 0:
        super().__init__(i)


int_t = IntTuple([2, -2, 'jr', ['x', 'y'], 4])
print(int_t)  # TypeError: object.__init__() takes no parameters

打印self

class IntTuple(tuple):
    def __init__(self, iterable):
        # for i in iterable:
        #     if isinstance(i, int) and i > 0:
        # super().__init__(i)
        print(self)


int_t = IntTuple([2, -2, 'jr', ['x', 'y'], 4])
print(int_t)
# (2, -2, 'jr', ['x', 'y'], 4)
# (2, -2, 'jr', ['x', 'y'], 4)

self 是谁创建的呢? 接下来研究对象中的"new"方法

class A(object):
    def __new__(cls, *args, **kwargs):
        print('__new__...', cls, args)
        return object().__new__(cls)

    def __init__(self, *args):
        print('__init__....')


a = A(1, 2)
__new__... <class '__main__.A'> (1, 2)
__init__....

可见先执行new方法,在执行的init方法,且必须要返回object().new(cls),init方法才可以执行。所以真正创建对象的是new方法 , cls就是创建的类

所以a = A(1,2)在python中执行顺序为
a = A.new(A, 1, 2),A.init(a, 1, 2)

接下来举个例子说明一下列表与元组的创建顺序

列表
l = list('abc')
print(l) # ['a', 'b', 'c']

l = list.__new__(list, 'abc')
print(l) # []
list.__init__(l, 'abc')
print(l) # ['a', 'b', 'c']

元组
t = tuple('def')
print(t) # ('d', 'e', 'f')

t = tuple.__new__(tuple, 'def')
print(t) # ('d', 'e', 'f')

所以说明在new方法中元组已经被创建好,在init方法中在进行修改就会出错,所以要在new方法进行修改
元组

class IntTuple(tuple):
    def __new__(cls, iterable):
        # 生成器
        f = (i for i in iterable if isinstance(i, int) and i > 0)
        return super().__new__(cls, f) # 这里也可以用IntTuple代替cls不过会使代码变为硬编码,不利于修改

int_t = IntTuple([2, -2, 'jr', ['x', 'y'], 4])

print(int_t) # (2, 4)

列表

class IntList(list):
    def __new__(cls, *args):
        print('new', cls, args)

        return super().__new__(cls, args)

    def __init__(self, arg):
        f = [i for i in arg if isinstance(i, int) and i > 0]
        print(f)


a = IntList([1, 2, 3, -1, -2, -3])
# new <class '__main__.IntList'> ([1, 2, 3, -1, -2, -3],)
# [1, 2, 3]


l = IntList.__new__(IntList, (1, 2))
IntList.__init__(l, (1, 2))
# new <class '__main__.IntList'> ((1, 2),)
# [1, 2]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值