【问题标题】:Python: Inherit class functions (property getter) does not workPython:继承类函数(属性获取器)不起作用
【发布时间】:2013-01-14 08:03:11
【问题描述】:

考虑以下代码:

class BaseClass(object):
    def _del_property(attr):
        """Abstract deller"""
        def del_attr(self):
            setattr(self, attr, None)
        return del_attr

    def _set_property(attr):
        """Abstract setter."""
        def set_attr(self, x):
            setattr(self, attr, x)            
        return set_attr

    def _get_property(attr):
        """Abstract getter"""
        def get_attr(self):
            getattr(self, attr)
        return get_attr

    _name = None
    name = property(fget=_get_property('_name'), fset=_set_property('_name'))


class Component(BaseClass):

    _material = None
    material = property(fget=_get_property('_material'), fset=_set_property('_material'), fdel=_del_property('_material'))

_get_property、_set_property 和 _del_property 怎么不被继承? 如何实现?

它应该适用于同一源文件中的派生类,也适用于单独文件中的派生类,后者使用

导入此源文件
from filename import *

【问题讨论】:

    标签: python inheritance properties


    【解决方案1】:

    创建类时,会创建一个新的命名空间。 Python 读取类块中的代码块,然后将信息传递给type(或相应的元类)。在这种情况下,python 会抱怨,因为在设置 Component 类时,_get_property 没有在该范围内定义——也许是 BaseClass._get_property,但这可能也不会像你想要的那样工作。

    一个简单的解决方法是使这些函数成为模块级函数,因为类命名空间可以访问模块命名空间:

    def _del_property(attr):
        """Abstract deller"""
        def del_attr(self):
            setattr(self, attr, None)
        return del_attr
    
    def _set_property(attr):
        """Abstract setter."""
        def set_attr(self, x):
            setattr(self, attr, x)            
        return set_attr
    
    def _get_property(attr):
        """Abstract getter"""
        def get_attr(self):
            getattr(self, attr)
        return get_attr
    
    
    class BaseClass(object):
    
        _name = None
        name = property(fget=_get_property('_name'), fset=_set_property('_name'))
    
    
    class Component(BaseClass):
    
        _material = None
        material = property(fget=_get_property('_material'), fset=_set_property('_material'), fdel=_del_property('_material'))
    

    也许在我们创建类时查看它更有启发性:

    class BaseClass(object):
    
        def _del_property(attr):
            """Abstract deller"""
            def del_attr(self):
                setattr(self, attr, None)
            return del_attr
    
        print type(_del_property)
    print type(BaseClass._del_property)
    

    这将打印:

    <type 'function'>
    <type 'instancemethod'>
    

    所以,您正在处理BaseClass 中的常规函数​​,但在type 之后它变成了instancemethod,这很神奇。


    就我个人而言,我只想创建一个方便的函数:

    def property_api(name,fget=True,fset=True,fdel=True):
        return property(fget=_get_property(name) if fget else None,
                        fset=_set_property(name) if fset else None,
                        fdel=_del_property(name) if fdel else None)
    

    然后您可以使用它。如果你真的想,你甚至可以把它放在BaseClass 作为staticmethod

     class BaseClass(object):
          property_api = staticmethod(property_api)
    

    那么您的派生类将如下所示:

     class DerivedClass(BaseClass):
          _material = None
          material = BaseClass.property_api('_material')
    

    【讨论】:

    • 是的,这适用于同一个 Python 文件中的派生类。但是,如果我从该文件中导入所有内容,则单独文件中的其他派生类仍然会抱怨。
    • 最后一个比我要找的还要好,谢谢!
    • 导入“一切”(可能是通过 import *)会跳过以下划线开头的名称。因此,如果您想继续调用它们 _get 等,则必须显式导入这些函数。
    猜你喜欢
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    相关资源
    最近更新 更多