Python: How to pass more than one argument to the property getter?

流过昼夜 提交于 2019-12-02 18:42:34

Note that you don't have to use property as a decorator. You can quite happily use it the old way and expose the individual methods in addition to the property:

class A:
    def get_x(self, neg=False):
        return -5 if neg else 5
    x = property(get_x)

>>> a = A()
>>> a.x
5
>>> a.get_x()
5
>>> a.get_x(True)
-5

This may or may not be a good idea depending on exactly what you're doing with it (but I'd expect to see an excellent justification in a comment if I came across this pattern in any code I was reviewing)

I think you did not fully understand the purpose of properties.

If you create a property x, you'll accessing it using obj.x instead of obj.x(). After creating the property it's not easily possible to call the underlying function directly.

If you want to pass arguments, name your method get_x and do not make it a property:

def get_x(self, neg=False):
    return 5 if not neg else -5

If you want to create a setter, do it like this:

class A:
    @property
    def x(self): return 5

    @x.setter
    def x(self, value): self._x = value

a property should only depend on the related object. If you want to use some external parameters, you should use methods.

In your second example, you're using a.x() as if it were a function: a.x(neg=True). With this in mind, why not just define it as a function?

I know this question is old, but, for reference, you can call your property with an argument like that:

a = A()
assert a.x == 5
assert A.x.fget(a, True) == -5

As other mentioned by others, this is not advised.

In this particular case, you could define two properties, which call an underlying function:

class A:
    @property
    def x(self):
        return self._x(neg = False)

    @property
    def x_neg(self):
        return self._x(neg = True)

    def _x(self, neg):
        return 5 if not neg else -5

I just ran into this issue. I have class Polynomial() and I'm defining a gradient that I would like to return a function if no arguments or evaluate if there are arguments. I want to store the gradient as an attribute so I don't need to calculate it every time I need to use it, and I want to use @property so the gradient attribute is calculated lazily. My solution was to define a class Gradient with a defined call method for Polynomial's grad property to return.

@property
def grad(self):
    """
    returns gradient vector
    """
    class Gradient(list):
        def __call__(self, *args, **kwargs):
            res = []
            for partial_derivative in g:
                res.append(partial_derivative(*args, **kwargs))
            return res
    g = Gradient()
    for i in range(1, len(self.term_matrix[0])):
        g.append(self.derivative(self.term_matrix[0][i]))
    return g

And then I have the following tests pass successfully:

def test_gradient(self):
    f = Polynomial('x^2y + y^3 + xy^3')
    self.assertEqual(f.grad, [Polynomial('2xy + y^3'), Polynomial('x^2 + 3xy^2 + 3y^2')])
    self.assertEqual(f.grad(x=1, y=2), [12, 25])
    f = Polynomial('x^2')
    self.assertEqual(f.grad(1), [2])

So, for this issue we could try:

class A:
    @property
    def x(self):
        class ReturnClass(int):
            def __call__(self, neg=False):
                if not neg:
                    return 5
                return -5
        return ReturnClass()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!