python属性引用成员属性的属性/属性?

时间:2018-07-18 07:34:36

标签: python-3.x class properties

我想知道是否有:

class A(object):
    def __init__(self):
        self.attribute = 1
        self._member = 2
    def _get_member(self):
        return self._member
    def _set_member(self, member):
        self._member = member
    member = property(_get_member, _set_member)

class B(object):
    def __init__(self):
        self._member = A()
    def _get_a_member(self):
        return self._member.member
    def _set_a_member(self, member):
        self._member.member = member
    member = property(_get_a_member, _set_a_member)

我能以某种方式避免编写A.member的get / setter方法,而仅引用A对象的属性或属性吗?

get / setter执行逻辑的地方当然是需要的,但是如果我只是不想公开成员属性的成员/属性,那么编写get / setter似乎很麻烦。

我认为即使我可以编写内联的get / setter方法也可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

我发现这个问题有点不清楚,但是我尝试解释一些上下文。

  

get / setter进行逻辑处理的地方当然是需要的,但是如果我只是不想公开成员属性的成员/属性

如果getter / setter中没有逻辑,则无需将属性定义为property,但是可以直接使用该属性(在任何上下文中)。

所以

class A(object):
    def __init__(self):
        self.attribute = 1
        self.member = 2

class B(object):
    def __init__(self):
        self.member = A()

B().member.member  # returns 2
B().member.member = 10

在某些语言中,使用getter / setter方法抽象实例属性被认为是一种好习惯,在Python中不一定是这种情况。 当您需要对属性进行更多控制时,Python属性非常有用,例如:

  • 有逻辑(验证等)时
  • 定义一个只读属性(所以只提供一个没有setter的getter)

更新(在评论后)

属性不一定是“隐藏”某些内部实现的工具。由于Python语言的动态特性,在Python中隐藏与在Java中隐藏有所不同。随时可以进行内部检查甚至更改对象,您可以在运行时向对象添加新属性(甚至方法):

b = B()
b.foo = 4  # define a new attribute on runtime
b.foo  # returns 4

因此,Python开发人员更多地依靠conventions来暗示他们的抽象意图。

关于多态成员,我认为Python类仅共享一个接口是最自然的,这就是Duck typing的含义。因此,只要您的A的下一个实现支持相同的接口(为调用者提供相同的方法),更改其实现就不会成为问题。

答案 1 :(得分:0)

这就是我想出的-使用一种方法来生成属性,并假设obj的属性为_member:

def generate_cls_a_property(name):
    """Small helper method for generating a 'dumb' property for the A object"""
    def getter(obj):
        return getattr(obj._member, name)

    def setter(obj, new_value):
        setattr(obj._member, name, new_value)

    return property(getter, setter)

这使我可以添加如下属性:

class B(object):
    def __init__(self):
        self._member = A()
    member = generate_cls_a_property('member')  # generates a dumb/pass-through property

我会接受我自己的,除非有人在一周之内将其加满。.:)