简体   繁体   English

如何将使用实例变量的实例方法作为另一个函数的参数传递?

[英]How to pass an instance method, that uses instance variables, as argument to another function?

I want to pass a method foo of an instance of a class A to another function run_function . 我想将类A的实例的方法foo传递给另一个函数run_function The method foo will use instance variables of its class A . 方法foo将使用其类A实例变量。

Here is a minimal example, in which the instance variable of A is simply self.a_var , and foo just prints that variable. 这是一个最小的例子,其中A的实例变量只是self.a_var ,而foo只是打印该变量。

class A:
    def __init__(self,a_var):
        self.a_var=a_var
    def foo(self):
        print(self.a_var)


class B:
    def __init__(self, A):
        self.A=A

        # EDIT (comment to compile)
        self.A.do_something()

    def run_function(self):
        self.A.foo()
    def run_function_2(self, bar):
        bar()



myA = A(42)
myA.foo()

# Current implementation
myB=B(myA)
myB.run_function()

# Better(?) implementation
myB.run_function_2(myA.foo)

At the moment I pass the instance myA of class A to the instance of B and explicitly call self.A.foo() . 目前,我将类A的实例myA传递给B的实例,并显式调用self.A.foo() This forces the name of the function of A to be foo . 这会强制A的函数名称为foo Which is stupid. 这是愚蠢的。

The better (?) implementation passes the function of the instance to run_function2 . 更好的(?)实现将实例的功能传递给run_function2 This works, but I am not sure if this is "safe". 这有效,但我不确定这是否“安全”。

Question: 题:

Are there any loopholes that I don't see at the moment? 我目前没有看到任何漏洞吗?

The important part is, that the method foo , that is passed, needs to access instance variables of the (its) class instance. 重要的是,传递的方法foo需要访问(它)类实例的实例变量。 So, will foo that is called inside run_function_2 always have access to all instance variables of myA ? 因此,将foo那个叫内run_function_2始终可以访问所有实例变量myA

Is there a better way to implement this? 有没有更好的方法来实现这个?

EDIT: I forgot to add, that class B will always have an instance of A , since it has to do_something with that instance. 编辑:我忘了添加, class B将始终有一个A的实例,因为它必须与该实例做do_something Maybe that will change something(?). 也许这会改变一些事情(?)。 Sorry! 抱歉!

To answer your questions: 回答你的问题:

  1. Any function executed in the context of an object instance will have access to the instance variables. 在对象实例的上下文中执行的任何函数都可以访问实例变量。
  2. There may be a better way to implement this, you could try defining an interface for class A and other classes that might be like it. 可能有更好的方法来实现它,您可以尝试为类A和其他可能类似的类定义接口。 The you know that the function will always be called foo(). 你知道该函数将永远被称为foo()。 If not, I'd question why it is you need to have some object call an arbitrary method on another object. 如果没有,我会问为什么你需要让一些对象调用另一个对象上的任意方法。 If you can give more concrete examples about what you're trying to do it would help. 如果你能给出更具体的例子来说明你想要做什么,那将会有所帮助。

For your second implementation, have you considered the following: 对于第二次实施,您是否考虑过以下事项:

>>> myAa = A(42)
>>> myAb = A(43)
>>> myB = B(myAb)
>>> myB.run_function_2(myAa.foo)
42

This might not be what you want. 这可能不是你想要的。 How about using getattr() and just passing in the desired method name: 如何使用getattr()并只传入所需的方法名称:

>>> class C:
...     def __init__(self, A):
...             self.A = A
...     def run_fct(self, bar):
...             fct = getattr(self.A, bar)
...             fct()
... 
>>> myC = C(myAa)
>>> myC.run_fct('foo')
42

The main difference between run_function and run_function_2 is that the former calls foo on the object that was given to the B() constructor. run_functionrun_function_2之间的主要区别在于前者在给予B()构造函数的对象上调用foo run_function_2 is independent of what object is saved as self.A ; run_function_2独立于保存为self.A对象; it just calls the function/method you give it. 它只是调用你给它的函数/方法。 For example 例如

class A:
    def __init__(self,a_var):
        self.a_var=a_var
    def foo(self):
        print(self.a_var)


class B:
    def __init__(self, A):
        self.A=A
    def run_function(self):
        self.A.foo()
    def run_function_2(self, bar):
        bar()

myA = A(42)
myB = B(myA)
myA2 = A(3.14)

myB.run_function()
myB.run_function_2(myA.foo)
myB.run_function_2(myA2.foo)

Output 产量

42
42
3.14

Are there any loopholes that I don't see at the moment? 我目前没有看到任何漏洞吗?

These two ways of calling methods are fine. 这两种调用方法的方法都很好。 Though I agree that function_run_2 is more convenient since it doesn't fix the method name, it makes you ask... what's the purpose of giving an A object to the B constructor in the first place if it's never used? 虽然我同意function_run_2更方便,因为它没有修复方法名称,但是它会让你问......如果A对象从未使用过,它首先给B构造函数提供了什么目的?

The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. 重要的是,传递的方法foo需要访问(它)类实例的实例变量。 So, will foo that is called inside run_function_2 always have access to all instance variables of myA? 那么,在run_function_2里面调用的foo总能访问myA的所有实例变量吗?

Yes. 是。 run_function_2 arguments requires a function. run_function_2参数需要一个函数。 In this case, you pass myA.foo , an object myA 's method defined in class A . 在这种情况下,您传递myA.foo ,这是在class A定义的对象myA的方法。 When you call foo inside run_function_2 , you are only dealing with attributes variables of the instance myA ; 当你在run_function_2调用foo ,你只处理实例myA属性变量; this is the idea of encapsulation in classes. 这是在类中封装的想法。

Is there a better way to implement this? 有没有更好的方法来实现这个?

Answering also your question on safety, it's perfectly safe. 回答你关于安全的问题,这是非常安全的。 Functions and methods are objects in Python, and they can be passed around like values. 函数和方法是Python中的对象,它们可以像值一样传递。 You're basically leaning on the idea of function currying or partial functions. 你基本上倾向于函数currying或部分函数的想法。 See How do I pass a method as a parameter in Python . 请参见如何在Python中将方法作为参数传递 These two ways are fine. 这两种方式都很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM