【问题标题】:get object on which a method was called in Python获取在 Python 中调用方法的对象
【发布时间】:2018-11-16 10:57:31
【问题描述】:

在 Python 中有没有办法获得对调用方法的对象的引用?

如果是这样,是否有可能以嵌套方式进行?

my_class.py:

from modules import math_ops

class A():
    def __init__(self):
        self.math_ops = math_ops.B()
        self.number = 1

模块/math_ops.py:

class B():
    def add_1():
        where_to_add = # Get instance of A() object
        where_to_add.number += 1

要执行这个:

>>> a = A()
>>> a.math_ops.add_1()

得到这个:

>>> a.number
2

我问这个问题是因为我有兴趣编写一个与调用它的对象一起工作的静态方法,但我想避免使用该对象作为参数,因为调用像 @ 这样的方法会更好987654325@ 而不是 my_object.prop.static_method(my_object)

【问题讨论】:

  • 如果您的静态方法需要调用它的对象,为什么不直接使用常规实例方法?
  • 如果你的意思是在B.add_1() 中使用self,那么它会引用B 的实例(例如A.math_ops)而不是A 的实例,我想。
  • 那我猜你有问题的语句不是my_object.static_method(my_object),而是my_object.prop.static_method(my_object)。对吗?
  • 哎哟。对了,我忘了把它放在那里。对不起。已编辑。

标签: python


【解决方案1】:

如果您从不打算在A 之外重新分配math_ops,这很容易做到。

from modules import math_ops

class A():
    def __init__():
        self.math_ops = math_ops.B(self)
        self.number = 1

模块/math_ops.py:

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

    def add_1():
        creator.number += 1

如果您略过第一行,我会再次提及它,因为B 正在跟踪对象的创建者而不是调用者,因此以下内容会产生意想不到的结果。

a1 = A()
a2 = A()
a1.math_ops = a2.math_ops
a1.math_ops.add_1() # a2 is updated

如果这看起来像是您可能想做的事情,那么答案会稍微复杂一些。这是我的尝试:

from modules import math_ops
class A():
    def __init__(self):
        self._math_ops = math_ops.B(self)
        self.number = 1

    @property
    def math_ops(self):
        self._math_ops.set_caller(self)
        return self._math_ops

    @math_ops.setter
    def math_ops(self, new_math_ops):
        self._math_ops = new_math_ops

模块/math_ops.py:

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

    def set_caller(self, caller):
        self.caller = caller

    def add_1(self):
        self.caller.number += 1

【讨论】:

  • 看起来不错,但有一个问题:它会不会创建一个循环链接,因此内存泄漏也有可能保留对 B 中的 A 对象的引用,因为我们也在保留来自AB 的引用?
  • @pesekon2 如果他们没有删除方法,则不会。见this answer
  • 哦,我明白了。这肯定是正确的答案,在接受它之前还有一个问题:内存没有立即释放,然后当我在一个循环中创建很多大对象时,会相互请求(例如,在每个循环中是a1 = A()),不使用gc.collect() 时内存不足。除了将其包含在属性定义中之外,还有其他方法可以避免它吗?
  • @pesekon2 您不必使用gc.collect()。默认情况下,python 中的 gc 是启用的。它会在您耗尽内存之前自动收集无人认领的对象。
【解决方案2】:
class A():
   number = 1

class B():
    def add_1():
        where_to_add = A
        where_to_add.number += 1

B.add_1()
print(A.number)
B.add_1()
print(A.number)
B.add_1()
print(A.number)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多