简体   繁体   English

了解Python类实例化

[英]Understanding Python class instantiation

Trying to figure out class inheritance of class attributes that are themselves classes. 试图找出本身就是类的类属性的类继承。 Here's what I'm trying to do: 这是我想做的事情:

class foo:
    hello = None
    world = None

    def __init__(self, **kwargs):
        for k,v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
            else:
                raise AttributeError(f'class foo has no attribute {k}')


class foo2:
    hi = None
    earth = None

    def __init__(self, **kwargs):
        for k,v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
            else:
                raise AttributeError(f'class foo has no attribute {k}')

class bar:
    foo_attr = foo(hello=1, world=2)
    foo2_attr = foo2(hi=3, earth=4)


class bar2(bar):
    def __init__(self):
    super().__init__()

So I have 2 base classes ( foo and foo2 ) with 2 attributes each ( hello & world , hi & earth , respectively). 所以我有2个基类( foo and foo2 ),每个都有2个属性(分别是helloworldhiearth )。

I have another base class ( bar ) that has class attributes inside with default values for foo and foo2 . 我还有另一个基类( bar ),其中具有类属性,其中默认值为foofoo2

Update (to include question): 更新(包括问题):

Lastly, I have bar2 which is a subclass of bar . 最后,我有bar2 ,它是bar的子类。 How can I change the values of an attribute of a subclass that are themselves, classes? 如何更改本身就是类的子类的属性的值? (say hello attribute of the foo_attr in bar2) (例如在bar2中foo_attr的hello属性)

I'm trying to set a default value for bar but i want to be able to set different attributes for each of the class attributes inside bar when I subclass it. 我正在尝试为bar设置默认值,但是我希望能够在对sub进行子类化时为bar中的每个类属性设置不同的属性。 This way, I can create a bunch of subclasses of bar like so: 这样,我可以创建一堆bar的子类,如下所示:

a bar2 with default attributes except foo2.earth which i set to 20. So that means bar2 has: 一个bar2具有默认属性,但我将foo2.earth设置为20。所以这意味着bar2具有:

  • foo.hello = 1 foo.hello = 1
  • foo.world = 2 foo.world = 2
  • foo2.hi = 3 foo2.hi = 3
  • foo2.earth = 20 foo2.earth = 20

and then still be able to create a bar3, with say default attributes for foo() and foo2() except for foo.hello, which maybe I want to set to 30 and then add a new attribute of say "jeez". 然后仍然能够创建bar3,除了foo.hello之外,它具有foo()和foo2()的默认属性,也许我想将其设置为30,然后添加一个新属性“ jeez”。

How do I go about doing this? 我该怎么做呢?

It looks like you want to create an explicit constructor for bar and bar2 so that you can choose the attributes: 看来您想为barbar2创建一个显式构造函数,以便可以选择属性:

class bar:
    def __init__(self, hello=1, world=2, hi=3, earth=4)
        self.foo_attr = foo(hello=hello, world=world)
        self.foo2_attr = foo2(hi=hi, earth=earth)

class bar2:
    def __init__(self)
        bar.__init__(self, earth=20)

You can still add new attributes in the new classes. 您仍然可以在新类中添加新属性。

I think you need to put the functionality into foo and foo2 and you have less duplication if those inherit from a common super class with the functionality. 我认为您需要将功能放入foofoo2并且如果这些功能从具有该功能的公共超类继承,则重复次数会减少。 The below script works (I had to remove the 'f' strings because I'm mired in the dark old days of python 3.5). 下面的脚本有效(我不得不删除'f'字符串,因为我陷入了Python 3.5的黑暗年代)。 There is still some work implementing the bar subclasses, but relatively sane. 仍然有一些实现bar子类的工作,但是相对理智。

import copy

class Fooinator:

    def __init__(self, **kwargs):
        badniks = self._update_instance(**kwargs)
        if badniks:
            raise AttributeError('class foo has no attributes {}'.format(badniks))

    def _update_instance(self, **kwargs):
        """Update self for variables defined at the class level returning
        names of variables not used by this class. """
        badniks = []
        for k,v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
            else:
                badniks.append(k)
        return badniks

    def opt_clone(self, **kwargs):
        """Given keyword arguments, clone a copy of self if any of them are
        used by this class, else return self."""
        for k in kwargs:
            if hasattr(self, k):
                me_2 = copy.copy(self)
                me_2._update_instance(**kwargs)
                return me_2
        return self


class foo(Fooinator):
    hello = None
    world = None


class foo2(Fooinator):
    hi = None
    earth = None


class bar:
    foo_attr = foo(hello=1, world=2)
    foo2_attr = foo2(hi=3, earth=4)


class bar2(bar):
    foo2_attr = bar.foo2_attr.opt_clone(earth=20)

b = bar2()
print(b.foo_attr.hello, b.foo_attr.world, b.foo2_attr.hi, b.foo2_attr.earth)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM