Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类方法是否会引用类实例而不是通过自身导致circ依赖,以及如何应对它?_Python_Circular Dependency - Fatal编程技术网

Python 类方法是否会引用类实例而不是通过自身导致circ依赖,以及如何应对它?

Python 类方法是否会引用类实例而不是通过自身导致circ依赖,以及如何应对它?,python,circular-dependency,Python,Circular Dependency,如果类B是a的子类,下面的代码会导致循环依赖吗? (为了简单起见,我不区分A,B和A(),B()) 我知道,这很容易解决 def random_function(A,B): do_stuff(A, B) class A: def method(self): # get B b = A.B random_function(self, b) 。。。但是我想知道我是否仍然可以只保留一个参数的签名 如果这太抽象了,那么这就是

如果类B是a的子类,下面的代码会导致循环依赖吗? (为了简单起见,我不区分A,B和A(),B())

我知道,这很容易解决

def random_function(A,B):
    do_stuff(A, B)   



class A:

    def method(self):
        # get B
        b = A.B
        random_function(self, b)
。。。但是我想知道我是否仍然可以只保留一个参数的签名

如果这太抽象了,那么这就是为什么我要问:在Blender中,有一个套接字类和一个节点类,其中套接字是节点的子类。我有一个子类node和一个函数,如下所示:

def func(socket):
    # get parent
    node = socket.node
    do_stuff(node, socket)

class sub_class(Node):

    def method(self):
        func(self.Socket)
有没有一种方法可以让函数签名只包含一个参数,而不会在这里陷入循环依赖

编辑:提供一些实际代码和上下文的编辑,在注释中遵循建议

我将从我认为导致循环引用的类的描述开始

ShaderNodeCustomGroup
表示一个节点—一种来自可视化编程的东西。它有套接字,它正在监听这些套接字上发生的事情。用户将输入连接到输入套接字,可以从输出套接字获取输出。基本上是非编程用户函数的可视化表示。虚幻也有这个,但我的是搅拌机

Socket
,上面已经提到过-这是可以接受输入和提供输出的

我不知道它们到底是如何交互的——这是在源代码中定义的,我只是在使用API,但如果我执行以下操作,我会使整个应用程序崩溃:

导致崩溃的函数:

def get_socket_neighbor(socket, offset):
    """
        get the neighbor of this socket, whose position is specified by the offset
        RETURNS: a socket or OUT_OF_RANGE
        NOTE: offset is not for the Blender socket order, it's acual movement by 'offset' socket up or down in world coordinates
    """
    sock_ind = get_socket_index(socket, socket.node)
    desired_position = sock_ind - offset # <--- the actual position in 'blender coordinates'
    if desired_position > (len(socket.node.inputs)-1) or desired_position < 0:
        return OUT_OF_RANGE
    else: 
        return socket.node.inputs[desired_position]
与您相关的是
mf.get\u socket\u neighbor(link.to\u socket,-1)。is\u NULL\u layer
。 这里,节点的类为函数提供了一个if套接字,然后它试图找到这个套接字的节点,即调用类本身

总之,子类的方法将子类的套接字提供给一个函数,然后该函数尝试访问套接字的节点,即子类本身。如果我重新编译代码,使函数只接受self,而不必访问socket.node,那么一切都可以正常工作


所以,我的问题是:这是循环引用吗?如果是,有没有办法克服它?我很在意,因为这会降低使用类的合理性:例如,我无法定义访问其节点的套接字属性。因为如果从节点方法内部使用此属性,也会使应用程序崩溃

这里没有明确显示或暗示的父/子关系。B.A和A.B不建议父母/子女关系。他们只是说B包含一个名为“A”的属性,A包含一个名为“B”的属性。这一点都没有错(撇开命名约定不谈)。这两个名字彼此无关,也与父/子关系无关。在B.A的情况下,“A”与名为“A”的类无关

关于:

# random_function will reference A now, but not via self, is this a problem?

不,random_函数将不引用A。random_函数将引用A类的B属性包含的任何内容。

我认为您关于不存在父/子关系的说法是正确的。另外,
random\u function()
引用了作为其
B
参数传递给它的任何was参数的
A
属性,该参数可能根本不是类。有了这段代码,您根本不知道发生了什么。这段代码本身当然不会运行。为了让它运行,必须定义A的“B”属性,不管是什么,它必须有一个名为“A”的属性。是的,不清楚OP到底在问什么——这就是为什么我自己没有尝试回答它(以及为什么我在之前的评论中说“思考”).我觉得我可以说点什么,因为OP显然认为A.B和B.A以某种方式表示父母/子女关系。我只是想指出那不是真的。谢谢你的回答。我在一开始就明确提到B是一个类。代码中定义了,因此它也是一个类。实际上,这是在应用程序运行时崩溃。对不起,这是一段抽象的代码,我会在一段时间内把它删掉。我为你在这方面再冒一次险而鼓掌。我明天再看我喜欢你用一个象征性的例子来保持简单的想法。也许你可以再试一次,但是试着从父/子、循环引用等方面体现你认为存在的问题。如果你能解释一下在实际遵循执行流程时你在哪里看到问题,那就太好了。我不想批评你的第一次尝试,然后不尽我所能帮助你。我真的觉得我需要这样做。计算机对我一直很好。想要回报……我可能需要你带我经历一下。@Steve听起来不错,谢谢。如果您对基础类和blender api有任何疑问,请随时提问。好的,我会在一段时间内对其进行几次编辑,然后你可以问还缺少什么,干杯@史蒂夫,我做了大量的编辑,但没有机会让它在任何程度上都可以理解,对不起。。。
class LayerStackNode(bpy.types.ShaderNodeCustomGroup):
            bl_label = "Layer Stack"

       .
       .
       .

        def insert_link(self, link):
    # runs on the insert of a link,
    # this is a preferred method when
    # it gets repaired by blender devs

        # check if the user is connecting mask
        if link.to_socket.name == "mask_layer":
            # simply draw a link from this socket to its mixer
            my_index = mf.get_socket_index(link.to_socket, self)
            relevant_layer = mf.get_socket_neighbor(link.to_socket, 1)
            relevant_mixer = mf.get_node_by_type(self.node_tree.nodes, 'GROUP_INPUT').outputs[my_index - 1].links[0].to_node
            self.node_tree.links.new(relevant_mixer.inputs[0], mf.get_node_by_type(self.node_tree.nodes, 'GROUP_INPUT').outputs[my_index])
            return

        def is_insert_input(self, link): 
        # determines whether the iserted link is input
            if link.to_socket.name == 'layer':
                return True
            else:
                return False

        if not is_insert_input(self, link):
            return  

        # if trying to insert on top of an empty layer, cancel and return
        if mf.get_socket_neighbor(link.to_socket, -1) != mf.OUT_OF_RANGE and \
            mf.get_socket_neighbor(link.to_socket, -1).is_NULL_layer:
            # TODO: find a way to undo the operation
            return

        if self.is_NULL_layer(link.to_socket): # proceed only if it's empty
            if not mf.get_socket_index(link.to_socket, self) == (len(self.inputs)-1): # <--- private case for the lowest layer in the stack
                if not self.is_NULL_layer(mf.get_socket_neighbor(link.to_socket, -1)):
                    self.initialize_layer(link.to_socket)
                else:
                    print("CANNOT MIX ONTO NULL LAYER")
            else:
                # when base layer, create a single link from input to output
                sock_index = mf.get_socket_index(link.to_socket, self)
                out = mf.get_node_by_type(self.node_tree.nodes, 'GROUP_INPUT').outputs[sock_index]
                inp = mf.get_node_by_type(self.node_tree.nodes, 'GROUP_OUTPUT').inputs[0]
                self.node_tree.links.new(inp, out)
        else:
            print("no action needed, the layer is not NULL") 

       .
       .
       .
# random_function will reference A now, but not via self, is this a problem?