我正在尝试创建名称基于类实例的特定属性的方法。我的代码与此类似:
class myClass:
info_to_be_accessed = {
'infoA': 14,
'infoB': 21,
'infoC': False,
'infoD': 'spam'
}
def create_methods(self):
for info in self.info_to_be_accessed:
setattr(self, info, lambda self: self.info_to_be_accessed.get(info, None))
return self
c = myClass().create_methods()
print(c.infoA())
我原本以为c.infoA()
是一个实例方法,但事实证明它是一个静态方法,在调用时没有获取self
参数。输出引发TypeError
:
Traceback (most recent call last):
File "test.py", line 15, in <module>
print(c.infoA())
TypeError: <lambda>() missing 1 required positional argument: 'self'
预期输出:
14
编辑:回答@chepner。老实说,我不确定这是处理它的最佳方法,但是我的基本问题是我正在处理数据库/我自己的代码之外的数据。我正在从一个我无法控制的数据库中检索信息,因此可以通过我的代码对其进行分析。基本上,我的真实代码类具有一个pandas数据框,其中包含有关复杂SQL查询的结果的信息以及绘制有关该图表的功能的信息,但有时我想过滤该数据框以进行绘制,有时我想绘制整个东西。我并不是真正在分析字典,而是创建方法来过滤此数据框。事实是,我正在使用此查询分析的(外部)对象具有某个属性可以是固定值,但是如果将来该外部数据库发生更改,我不想创建额外的代码来覆盖新值,被添加到那里。在分析这些数据时,使用方法而不是参数对我来说更方便,但这不是要投入生产的代码,而只是我在CLI上使用的代码。这就是为什么我对每个可以传递的值使用单独的方法很方便。
答案 0 :(得分:1)
(有点)回复wim的评论:
我自己还没有遇到好的用例,但是您可以设置 任意函数作为任意实例的方法。风格好吗?在大多数情况下,也许有更好的方法。但是您可以,我会告诉您。
您只是在设置一个恰好是您实例上的函数的属性。
函数是(非数据)descriptors,您可以使用它们的__get__
方法来固定第一个参数。
演示:
>>> class myClass:
...: def __repr__(self): # nicer output for demo
...: return '<myClass object>'
...: def create_method_on_instance(self, name, function):
...: setattr(self, name, function.__get__(self))
>>>
>>> m1 = myClass()
>>> m2 = myClass()
>>> m1.create_method_on_instance('foo', lambda self, x, y: print(self, x + y))
>>> m2.create_method_on_instance('foo', lambda self, x, y: print(self, x - y))
>>>
>>> m1.foo(3, 4)
<myClass object> 7
>>> m2.foo(3, 4)
<myClass object> -1
我无法在此处对Descriptor HowTo Functions and Methods section进行重申,但它会像这样分解:
当您通过点符号访问实例上的函数属性时,将不会调用函数的__get__
方法。
但是,函数的__get__
方法负责将函数的第一个参数(通常称为self
)绑定到所讨论的实例(从而创建方法)。
如果要通过任意实例上的任意函数创建方法,仍然可以手动调用__get__
。这可能有点愚蠢,因为您甚至可以将第一个函数参数绑定到某个实例,然后将该方法设置为另一个对象的属性;)
>>> class Unrelated:
...: pass
...:
>>> u = Unrelated()
>>> u.foo = (lambda self, x, y: print(self, x+y)).__get__(m1)
>>> u.foo(3, 4)
<myClass object> 7