隐藏/封装继承类中的所有属性,同时保留功能

2024-05-23 18:35:04 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有办法隐藏或嵌套Cat属性在Animal中,同时仍然能够运行跳转函数?具体来说,我希望vars(test)的输出仅为年龄。我确信我可以通过定义一个自定义的__str__硬编码哪些特定的属性不输出,但是我将有很多Cat/Animal的属性,我不想为每个单独的属性手动添加一个异常。我也不能访问Cat

def Jump():
    print('Jumped!')

class Cat:
    def __init__(self):
        self.feet = 4
        self.jump = Jump

class Animal(Cat):
    def __init__(self):
        Cat.__init__(self)
        self.age = 3

test = Animal()
test.jump()
print(vars(test))

输出:

Jumped {'feet': 4, 'jump': , 'age': 3}

这只是一段代码来说明我要做的事情。实际上,Cat表示已发布的python模块,Animal表示我的自定义模块


Tags: testselfage属性initdefvarsclass
1条回答
网友
1楼 · 发布于 2024-05-23 18:35:04

如果你改变你的关系,使Animal不再是一个^{Cat,而是一个^{Cat,那么你是对的,animal.jump()将不再工作

有很多方法可以解决这个问题。考虑到这个设计已经很奇怪了,在很多不同的方面,我不知道哪一个是最合适的,所以我只列出一大堆

第一组是只显式委托jump的方法

“正常”方式:

class Animal:
    def __init__(self):
        self.cat = Cat()
    def jump(self):
        return self.cat.jump()

复制每个实例函数:

class Animal:
    def __init__(self):
        self.cat = Cat()
        self.jump = self.cat.jump

委托给每个实例函数:

class Animal:
    def __init__(self):
        self.cat = Cat()
        self.jump = lambda: self.cat.jump()

每实例绑定方法:

class Animal:
    def __init__(self):
        self.cat = Cat()
        self.jump = (lambda self: self.cat.jump()).__get__(self)

动态查找:

class Animal:
    def __init__(self):
        self.cat = Cat()
    def __getattr__(self, name):
        if name == 'jump':
            return getattr(self.cat, name)
        raise AttributeError

动态绑定方法生成:

class Animal:
    def __init__(self):
        self.cat = Cat()
    def __getattr__(self, name):
        if name == 'jump':
            return (lambda self: getattr(self.cat, name)()).__get__(self)
        raise AttributeError

当然,所有这些都只是具体地委托jump。如果您想委托给所有Cat函数、方法,或者其他属性,而不必事先知道它们是什么,该怎么办?好吧,应该很明显如何适应这些,所以我只展示两个

动态查找:

class Animal:
    def __init__(self):
        self.cat = Cat()
    def __getattr__(self, name):
        return getattr(self.cat, name)

半静态检查,对我们可能要委托的不同类型的事情进行复杂的反映:

class Animal:
    def __init__(self):
        self.cat = cat
        for name, value in inspect.getmembers(self.cat):
            if name.startswith('_'): continue
            if inspect.ismethod(value):
                value = (lambda self: value()).__get__(self)
            elif callable(value):
                value = lambda: value()
            else:
                value = copy.copy(value)
            setattr(self, name, value)

相关问题 更多 >