如果基类的数据成员被重写为派生类中的属性,如何调用基类的数据成员?

发布于 2024-07-25 21:23:44 字数 708 浏览 6 评论 0原文

这个问题类似于 另一个,不同之处在于基类中的数据成员由描述符协议包装。

换句话说,如果我用派生类中的属性覆盖基类的成员,如何访问该成员?

class Base(object):
    def __init__(self):
        self.foo = 5

class Derived(Base):
    def __init__(self):
        Base.__init__(self)

    @property
    def foo(self):
        return 1 + self.foo # doesn't work of course!

    @foo.setter
    def foo(self, f):
        self._foo = f

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo

请注意,我还需要定义一个 setter,否则基类中 self.foo 的分配将不起作用。

总而言之,描述符协议似乎与继承不能很好地交互......

This question is similar to this other one, with the difference that the data member in the base class is not wrapped by the descriptor protocol.

In other words, how can I access a member of the base class if I am overriding its name with a property in the derived class?

class Base(object):
    def __init__(self):
        self.foo = 5

class Derived(Base):
    def __init__(self):
        Base.__init__(self)

    @property
    def foo(self):
        return 1 + self.foo # doesn't work of course!

    @foo.setter
    def foo(self, f):
        self._foo = f

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo

Please note that I also need to define a setter because otherwise the assignment of self.foo in the base class doesn't work.

All in all the descriptor protocol doesn't seem to interact well with inheritance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

2024-08-01 21:23:44

如果使用委托而不是继承,生活会更简单。 这是Python。 您没有义务从 Base 继承。

class LooksLikeDerived( object ):
    def __init__( self ):
        self.base= Base()

    @property
    def foo(self):
        return 1 + self.base.foo # always works

    @foo.setter
    def foo(self, f):
        self.base.foo = f

但是 Base 的其他方法呢? 您可以简单地复制 LooksLikeDerived 中的名称。

def someMethodOfBase( self, *args, **kw ):
    return self.base.someMethodOfBase( *args **kw )

是的,它并不感觉“干”。 然而,当像您尝试做的那样在新功能中“包装”某些类时,它可以防止很多问题。

Life is simpler if you use delegation instead of inheritance. This is Python. You aren't obligated to inherit from Base.

class LooksLikeDerived( object ):
    def __init__( self ):
        self.base= Base()

    @property
    def foo(self):
        return 1 + self.base.foo # always works

    @foo.setter
    def foo(self, f):
        self.base.foo = f

But what about other methods of Base? You duplicate the names in LooksLikeDerived and simply.

def someMethodOfBase( self, *args, **kw ):
    return self.base.someMethodOfBase( *args **kw )

Yes, it doesn't feel "DRY". However, it prevents a lot of problems when "wrapping" some class in new functionality like you're trying to do.

小红帽 2024-08-01 21:23:44

Base中定义

def __init__(self):
    self.foo = 5

使得foo成为实例的成员(属性),而不是类的成员(属性)。 Base 不了解 foo,因此无法通过 super() 等方式访问它代码>调用。

然而,这不是必需的。 当您实例化

foobar = Derived()

并调用基类的 __init__() 方法

self.foo = 5

时,这不会导致创建/覆盖属性,而是调用 Derived 的 setter ,意味着

self.foo.fset(5)

self._foo = 5。 因此,如果您放入

return 1 + self._foo

吸气剂,您几乎就会得到您想要的东西。 如果您需要在 Base 的构造函数中设置 self.foo 的值,只需查看 _foo,它是由@foo.setter

Defining

def __init__(self):
    self.foo = 5

in Base makes foo a member (attribute) of the instance, not of the class. The class Base has no knowledge of foo, so there is no way to access it by something like a super() call.

This is not necessary, however. When you instanciate

foobar = Derived()

and the __init__() method of the base class calls

self.foo = 5

this will not result in the creation / overwriting of the attribute, but instead in Derived's setter being called, meaning

self.foo.fset(5)

and thus self._foo = 5. So if you put

return 1 + self._foo

in your getter, you pretty much get what you want. If you need the value that self.foo is set to in Base's constructor, just look at _foo, which was set correctly by the @foo.setter.

绝影如岚 2024-08-01 21:23:44
class Foo(object):
    def __new__(cls, *args, **kw):
        return object.__new__(cls, *args, **kw)

    def __init__(self):
        self.foo = 5

class Bar(Foo):
    def __new__(cls, *args, **kw):
        self = object.__new__(cls, *args, **kw)
        self.__foo = Foo.__new__(Foo)
        return self

    def __init__(self):
        Foo.__init__(self)

    @property
    def foo(self):
        return 1 + self.__foo.foo

    @foo.setter
    def foo(self, foo):
        self.__foo.foo = foo

bar = Bar()
bar.foo = 10
print bar.foo
class Foo(object):
    def __new__(cls, *args, **kw):
        return object.__new__(cls, *args, **kw)

    def __init__(self):
        self.foo = 5

class Bar(Foo):
    def __new__(cls, *args, **kw):
        self = object.__new__(cls, *args, **kw)
        self.__foo = Foo.__new__(Foo)
        return self

    def __init__(self):
        Foo.__init__(self)

    @property
    def foo(self):
        return 1 + self.__foo.foo

    @foo.setter
    def foo(self, foo):
        self.__foo.foo = foo

bar = Bar()
bar.foo = 10
print bar.foo
愚人国度 2024-08-01 21:23:44

一旦您拥有相同名称“foo”的属性,它就会覆盖名称“foo”的访问行为
唯一的出路似乎是你在 dict 中显式设置 'foo'

顺便说一句:我使用 python 2.5 因此必须稍微更改代码

class Base(object):
    def __init__(self):
        self.foo = 5

class Derived(Base):
    def __init__(self):
        Base.__init__(self)

    def g_foo(self):
        return 1 + self.__dict__['foo'] # works now!

    def s_foo(self, f):
        self.__dict__['foo'] = f
        self._foo = f

    foo = property(g_foo, s_foo)

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo

once you have property with same name 'foo' it overrides the behaviour of access of name 'foo'
only way out seems that you explicitly set 'foo' in dict

btw: I use python 2.5 hence had to change code a bit

class Base(object):
    def __init__(self):
        self.foo = 5

class Derived(Base):
    def __init__(self):
        Base.__init__(self)

    def g_foo(self):
        return 1 + self.__dict__['foo'] # works now!

    def s_foo(self, f):
        self.__dict__['foo'] = f
        self._foo = f

    foo = property(g_foo, s_foo)

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo
小清晰的声音 2024-08-01 21:23:44

老实说,这里要注意的是,您正试图围绕一个很糟糕的设计来扭曲您的代码。 属性描述符处理对“foo”属性的请求,并且您希望完全绕过这些请求,这是错误的。 您已经使 Base.init 分配 foobar._foo = 5,因此这正是 getter 需要查找的位置。

基类(对象):
def init(自身):
自我.foo = 5

class Derived(Base):
  def __init__(self):
    Base.__init__(self)

  @property
  def foo(self):
    return 1 + self._foo # DOES work of course!

  @foo.setter
  def foo(self, f):
    self._foo = f

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo

Honestly, the thing to look at here is that you're trying to twist your code around a design that is simply poor. The property descriptors handle the request for a 'foo' attribute, and you want to bypass these completely, which is just wrong. You're already causing Base.init to assign foobar._foo = 5, so thats exactly where the getter needs to look, too.

class Base(object):
def init(self):
self.foo = 5

class Derived(Base):
  def __init__(self):
    Base.__init__(self)

  @property
  def foo(self):
    return 1 + self._foo # DOES work of course!

  @foo.setter
  def foo(self, f):
    self._foo = f

bar = Base()
print bar.foo

foobar = Derived()
print foobar.foo
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文