问题
我希望能够使用引用实例属性的函数初始化对象。我希望我尝试在此代码段中捕获,这会产生NameError: "global name 'self' is not defined"
:
class Test(object):
def __init__(self, function = None):
self.dicty = {1:{'height': 4, 'width': 2}, 2:{'height': 1, 'width': 2} }
if function == None:
self.function = lambda x : self.dicty[x]['height']
else:
self.function = function
if __name__ == '__main__':
def func1(x):
return self.dicty[x]['width']
def func2(x):
return self.dicty[x]['width']**2
G = Test(function = func1)
H = Test(function = func2)
我可以通过为Test
创建一堆子类来解决问题,但这似乎不可读。
动机
我正在使用NetworkX进行Python建模和实验。我正在查看经典的Albert-Barabasi Model并创建DiGraph类的子类,其中包括Preference(self, node)
,Attachment(self, parent, child)
,然后是Grow(self, max_allowable_nodes)
。我希望能够创建一个修改preference()
的实例,而不是像我之前提到的那样创建一大堆子类。这将允许我运行数值实验,而我的代码看起来不像弗兰肯斯坦那样。期待学习新的东西。
修改
不了解types
类或反射的一般概念。显然,这里仍然很新。非常感谢大家回答我的问题并指出我正确的方向!
答案 0 :(得分:2)
鉴于您在lambda
中创建的__init__
是指实例(self
),您似乎想要将方法附加到您的实例,而在这里你附加了一个函数。您需要从函数创建一个方法并将其附加到实例:
import types
class Test(object):
def __init__(self, function = None):
self.dicty = {1:{'height': 4, 'width': 2}, 2:{'height': 1, 'width': 2} }
if function == None:
function = lambda self, x: self.dicty[x]['height']
self.function = types.MethodType(function, self)
方法基本上是一个总是将实例作为第一个参数传递的函数,因此您需要确保传递给初始化函数的任何函数都以self
作为初始参数。
>>> t1 = Test()
>>> t1.function(1)
4
>>> t2 = Test(lambda self, x: self.dicty[x]['width'])
>>> t2.function(1)
2
答案 1 :(得分:1)
定义func1
时,不存在self
这样的事情。它不是函数的参数,它不在更高的范围内。
相反,您可以定义一个函数,该函数将您用作参数的dict
作为参数进行操作。在Test
课程中,您可以在self.dicty
上调用该函数。这需要您将lambda
更改为dicty
和x
,而不仅仅是x
。
def func1(dicty, x):
return dicty[x]['width']
...并在Test
...
class Test(object):
# ... current code but with lambda tweak:
# lambda dicty, x: dicty[x]['height']
def do_something(self, x):
self.function(self.dicty, x)
如果没有看到其余的代码,很难知道您可以进行哪些进一步的简化。但是,由于所有函数似乎都在使用dicty[x]
,所以你可以直接编写它们来直接使用它。