覆盖python中的属性 [英] Overriding properties in python

查看:141
本文介绍了覆盖python中的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我试图找出最好的(最优雅,代码最少)的方法来允许在python中覆盖属性的特定函数(例如,只是getter,只是setter等)。我喜欢以下做属性的方法,因为它们的所有方法都封装在相同的缩进代码块中(更容易看到处理一个属性的函数停止在哪里以及处理函数的函数下一步开始):

So, I'm trying to figure out the best (most elegant with the least amount of code) way to allow overriding specific functions of a property (e.g., just the getter, just the setter, etc.) in python. I'm a fan of the following way of doing properties, due to the fact that all of their methods are encapsulated in the same indented block of code (it's easier to see where the functions dealing with one property stop and the functions dealing with the next begin):

@apply
def foo():
    """A foobar"""
    def fget(self):
        return self._foo
    def fset(self, val):
        self._foo = val
    return property(**locals())

但是,如果我想从以这种方式定义属性的类继承,那么,比方说,覆盖 foo setter函数,看起来很棘手。我做了一些搜索,我发现的大多数答案都是在基类中定义单独的函数(例如 getFoo setFoo ),从它们显式创建一个属性定义(例如 foo = property(lambda x:x.getFoo(),lambda x,y:x.setFoo(y),lambda x :x.delFoo())),然后覆盖 getFoo setFoo ,以及 delFoo 根据需要。

However, if I want to inherit from a class that defines properties in this manner, and then, say, override the foo setter function, it seems tricky. I've done some searching and most of the answers I've found have been to define separate functions in the base class (e.g. getFoo and setFoo), explicitly create a property definition from them (e.g. foo = property(lambda x: x.getFoo(), lambda x, y: x.setFoo(y), lambda x: x.delFoo())), and then override getFoo, setFoo, and delFoo as needed.

我不喜欢这个解决方案,因为这意味着我必须为每个属性定义lambas,并且然后写出每个函数调用(之前我可以完成属性(** locals()))。我也没有得到我原来的封装。

I dislike this solution because it means I have to define lambas for every single property, and then write out each function call (when before I could have just done property(**locals())). I also don't get the encapsulation that I had originally.

理想情况下,我希望能够做到的是:

Ideally, what I would like to be able to do would be something like this:

class A(object):
    def __init__(self):
        self.foo = 8
    @apply
    def foo():
        """A foobar"""
        def fget(self):
            return self._foo
        def fset(self, val):
            self._foo = val
        return property(**locals())

class ATimesTwo(A):
    @some_decorator
    def foo():
        def fset(self, val):
            self._foo = val * 2
        return something

然后输出看起来像:

>>> a = A()
>>> a.foo
8
>>> b = ATimesTwo()
>>> b.foo
16

基本上, ATimesTwo A 继承getter函数,但会覆盖setter函数。有没有人知道这样做的方式(看起来类似于上面的例子)? some_decorator 的功能是什么样的, foo 函数应返回什么功能?

Basically, ATimesTwo inherits the getter function from A but overrides the setter function. Does anybody know of a way to do this (in a manner that looks similar to the example above)? What function would the some_decorator look like, and what should the foo function return?

推荐答案

我确定你之前听过这个,但 apply 已弃用八年,自Python 2.3以来。不要使用它。你使用 locals()也与Python的Zen相反 - 显式优于隐式。如果你真的喜欢增加缩进,就不需要创建一次性对象,只需要

I'm sure you've heard this before, but apply has been deprecated for eight years, since Python 2.3. Don't use it. Your use of locals() is also contrary to the Zen of Python -- explicit is better than implicit. If you really like the increased indentation, there is no need to create a throwaway object, just do

if True:
    @property
    def foo(self):
        return self._foo
    @foo.setter
    def foo(self, val):
        self._foo = val

哪些不滥用本地人,请使用 apply ,需要创建一个额外的对象,或者之后需要一行 foo = foo()让它变得更难看到块的结尾。它适用于您使用属性的老式方式 - 只需执行 foo = property(fget,fset)正常。

Which doesn't abuse locals, use apply, require creation of an extra object, or need a line afterwards with foo = foo() making it harder to see the end of the block. It works just as well for your old-fashioned way of using property -- just do foo = property(fget, fset) as normal.

如果要覆盖任意子类中的属性,可以使用这样的食谱

If you want to override a property in an arbitrary subclass, you can use a recipe like this.

如果子类知道属性已定义,只需:

If the subclass knows where the property was defined, just do:

class ATimesTwo(A):
    @A.foo.setter
    def foo(self, val):
        self._foo = val * 2

这篇关于覆盖python中的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆