这个python概念叫什么?使用childonly属性的父类。

2024-05-20 11:00:04 发布

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

我正在写一些代码,它是继承的倒三角形。我有一个基本的Linux类,它有一个客户端attr,它保存一个连接。我有几个逻辑上分离的api(kvm、yum、gdb、dhcp等等),它们使用CLIENT,但是我只希望用户需要创建一个Linux类的实例,但是能够调用父类中的所有方法。在保持父级之间良好的逻辑代码分离的同时:

class Linux(
SSHClient,
yum.Yum,
kvm.Kvm,
ldap.Ldap,
lshw.Lshw,
packet_capture.Tcpdump,
tc.TrafficControl,
networking.Networking,
gdb.Gdb,
dhcp.Dhcp,
httputil.Http,
scp.Scp,
fileutils.FileUtils):

我举了个小例子:

class Dad(object):
        def __init__(self):
                raise NotImplementedError("Create Baby instead")

        def dadCallBaby(self):
                print('sup {}'.format(self.babyName))

class Mom(object):
        def __init__(self):
                raise NotImplementedError("Create Baby instead")

        def momCallBaby(self):
                print('goochi goo {}'.format(self.babyName))

class Baby(Mom, Dad):
        def __init__(self, name):
                self.babyName = name

        def greeting(self):
                self.momCallBaby()
                self.dadCallBaby()

x=Baby('Joe')
x.greeting()

这叫什么?这只鸭子在打字吗?还有更好的选择吗?你知道吗


Tags: 代码selfobjectinitlinuxkvmdef逻辑
1条回答
网友
1楼 · 发布于 2024-05-20 11:00:04

真的不存在“只有孩子的属性”。你知道吗

属性babyName只是存储在每个对象的名称空间中,并在那里查找。Python并不关心它是由Baby.__init__存储的。事实上,您可以在Mom上写入并存储不是Baby的相同属性,其工作方式相同:

class NotABaby(Mom):
    def __init__(self): pass

mom = NotABaby()
mom.babyName = 'Me?'
mom.momCallBaby()

而且,很难提出一个更好的方法来做你正在做的事情,因为你正在做的事情本身就是令人困惑的,可能不应该做。你知道吗

继承通常意味着子类型化,也就是说,如果每个Baby实例都可用作Mom,那么Baby只能是Mom的子类

但是婴儿不是妈妈和爸爸。2婴儿有妈妈和爸爸。表示这一点的方法是为它的父母提供Baby属性:

class Baby(object):
    def __init__(self, mom, dad, name):
        self.mom, self.dad, self.name = mom, dad, name
    def greeting(self):
        self.mom.momCallBaby(self.name)
        self.dad.dadCallBaby(self.name)

注意,例如,这意味着同一个女人可以是两个孩子的妈妈。既然你在这里建模的真实事物也是如此,那就表明你在正确地建模。你知道吗


你的“真实”例子有点不太清楚,但我怀疑那里也发生了同样的事情。你知道吗

据我所知,您想要使用继承的唯一原因是:

I only want the user to need to create a single instance of Linux class

你不需要,也不想继承:

class Linux(object):
    def __init__(self):
        self.ssh_client = SSHClient()
        self.yum = yum.Yum()
        # etc.

… but be able to call all the methods from the Parent classes

如果yum.Yumldap.Ldapdhcp.Dhcp都有名为lookup的方法,那么Linux.lookup会调用哪个方法?你知道吗

您可能希望将这些属性保留为公共属性,并显式地使用它们:

system = Linux()
print(system.yum.lookup(package))
print(system.ldap.lookup(name))
print(system.dhcp.lookup(reservation))

或者您需要提供一个“Linux API”,它封装了所有底层API:

def lookup_package(self, package):
    return self.yum.lookup(package)
def lookup_ldap_name(self, name):
    return self.ldap.lookup(name)
def lookup_reservation(self, reservation):
    return self.dhcp.lookup(reservation)

如果您真的想转发所有不同组件的每个方法,并且您确定它们之间没有冲突,并且有太多的方法需要手动编写,那么您可以通过编程的方式来完成,通过迭代所有的类,迭代每个类的inspect.getmembers,筛选出以_开头或不是未绑定方法的方法,创建一个代理函数,并将其setattr放到Linux。你知道吗

或者,您也可以在方法查找时通过实现__getattr__方法(通常还有__dir__方法)来动态代理(在本例中可能不是一个好主意,但在没有太大区别的情况下非常有用)。你知道吗

我想这两种代理中的一种可能就是你真正想要的。你知道吗


1。在某些情况下,您希望继承的原因不是子类型。例如,您继承一个mixin类来获取一组方法的实现。类是否在mixin实例可用的任何地方都可用的问题实际上没有意义,因为mixin在任何地方都不可用(除了作为基类)。但是,子类型仍然是您正在弯曲的标准。

2。如果,请致电儿童保护服务中心。同时打电话给X教授,因为这在物理上是不可能的。

相关问题 更多 >