【问题标题】:Understanding Python class instantiation了解 Python 类实例化
【发布时间】:2018-04-07 20:50:32
【问题描述】:

试图找出本身就是类的类属性的类继承。这是我正在尝试做的事情:

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__()

所以我有 2 个基类 (foo and foo2),每个基类有 2 个属性(分别为 helloworldhiearth)。

我有另一个基类 (bar),其内部具有类属性,默认值为 foofoo2

更新(包括问题):

最后,我有bar2,它是bar 的子类。如何更改本身就是类的子类的属性值? (打个招呼 bar2 中 foo_attr 的属性)

我正在尝试为bar 设置默认值,但我希望能够在子类化时为 bar 内的每个类属性设置不同的属性。这样,我可以像这样创建一堆 bar 的子类:

a bar2 具有默认属性,但我设置为 20 的 foo2.earth 除外。这意味着 bar2 具有:

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

然后仍然能够创建一个 bar3,具有 foo() 和 foo2() 的默认属性,除了 foo.hello,也许我想将其设置为 30,然后添加一个新属性说“jeez” .

我该怎么做?

【问题讨论】:

  • 问题是什么
  • “我怎样才能改变一个子类本身的属性值,类”它们不是类...
  • 抱歉,正确的术语是类的实例吗?我仍在努力学习提出问题时要使用的所有正确术语。我的错!
  • 是的,它们是一个类的实例。但是 Python 中的 everything 是类的实例,甚至类本身也是如此。这就是为什么你会听到“Python 中的一切都是对象”。无论如何,你不能在bar2 中做foo2_attr = foo2(hi=3, earth=20) 吗?顺便说一句,我挖黑零分身。
  • 是的,从技术上讲我可以——但我的问题是:我正在制作的实际类有大约 10 多个同一个类的属性。如果说我有一个带有 10 个不同 foo_attr(即 foo1_attr、foo2_attr、...、foo10_attr)的 bar 类,并且我想将每个 foo{x}_attr 的所有 hello 属性更改为 1、2、3、.. .,8,9,10,从技术上讲,我可以再次分配所有内容。我希望找到一种 DRY 方法来在许多 bar 子类中执行此操作。

标签: python subclass


【解决方案1】:

您似乎想为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)

您仍然可以在新类中添加新属性。

【讨论】:

    【解决方案2】:

    我认为您需要将功能放入 foofoo2 中,如果它们继承自具有该功能的通用超类,则重复次数会更少。下面的脚本有效(我不得不删除'f'字符串,因为我陷入了python 3.5的黑暗旧时代)。实现 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 2015-07-27
      • 1970-01-01
      • 2023-04-08
      相关资源
      最近更新 更多