__init__,函数作为参数(使用NetworkX)

时间:2014-04-08 02:04:03

标签: python oop networkx

问题

我希望能够使用引用实例属性的函数初始化对象。我希望我尝试在此代码段中捕获,这会产生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类或反射的一般概念。显然,这里仍然很新。非常感谢大家回答我的问题并指出我正确的方向!

2 个答案:

答案 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更改为dictyx,而不仅仅是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],所以你可以直接编写它们来直接使用它。