考虑以下示例:
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
。
所以,我想知道如何将多个参数传递给属性获取器(如果可能的话)。
请注意,您没有使用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
如果你想创建一个setter,请这样做:
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
@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
然后我成功通过了以下测试:
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])
所以,对于这个问题我们可以尝试:
class A:
@property
def x(self):
class ReturnClass(int):
def __call__(self, neg=False):
if not neg:
return 5
return -5
return ReturnClass()
例如,我们可以根据不同的来源生成特定格式的数据,以进行进一步处理:
从 formatted_data 导入 FormattedData
数据生成器类:
class TYPE:
CSVFILE = 0
SQLITE = 1
HTTP = 2
@classmethod
def produceData(c, source_type: int, source_address) -> FormattedData:
match source_type:
case c.TYPE.CSVFILE:
pass
case c.TYPE.SQLITE:
pass
case c.TYPE.HTTP:
pass
调用此类方法:
DataGenerator.produceData(DataGenerator.TYPE.CSVFILE, '/financial_history.csv')
DataGenerator.produceData(DataGenerator.TYPE.SQLITE, '/financial_history.sqlite')