Python: как передать более одного аргумента в геттер свойств?

рассмотрим следующий пример:

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

так, конечно, называя a = A(); a.x вернутся 5

но представьте, что вы хотите иметь возможность изменять свойство x.
Вот так, например:

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

и вызовите его с a = A(); a.x(neg=True)

это поднимет TypeError:'int' object is not callable, это вполне нормально, так как наш x оценивается как 5.

Итак, я хотел бы знать, как можно передать более одного аргумента в собственность геттера, если это вообще возможно.

6 ответов


обратите внимание, что вы не есть использовать 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

Это может быть или не быть хорошей идеей в зависимости от того, что вы с ней делаете (но я ожидал бы увидеть отличное обоснование в комментарии, если бы я столкнулся с этим шаблоном в любом коде, который я просматривал)


Я думаю, вы не до конца поняли назначение свойств.

если вы создаете собственность x, вы получите доступ к нему с помощью obj.x вместо obj.x(). После создания свойства нелегко вызвать базовую функцию напрямую.

если вы хотите передать аргументы, назовите свой метод get_x и не делайте это свойством:

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

если вы хотите создать сеттер, делай так:

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

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

свойство должно зависеть только от связанного объекта. Если вы хотите использовать некоторые внешние параметры, вы должны использовать методы.


во втором примере вы используете a.x() как будто это функция:a.x(neg=True). Имея это в виду, почему бы просто не определить его как функцию?


Я знаю, что этот вопрос старый, но для справки вы можете вызвать свое свойство с таким аргументом:

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

Как и другие упомянутые другими, это не рекомендуется.


в этом конкретном случае вы можете определить два свойства, которые вызывают базовую функцию:

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