获取实例变量的类

时间:2017-12-03 15:55:50

标签: python class variables

我尝试获取实例变量的类,我认为这很简单,但目前我无法弄明白。

class A():
  def __init__(self):
    self.a = 1

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

def getClassOfVariable(abc):
  print(abc)

getClassOfVariable(B().b)
<__main__.A object at 0x7f4b2652ac18>

例如,我有一个函数,我将B()。b作为参数(为什么)传递给函数,在这个函数中我需要变量的类在哪里定义,所以类B()就是我想要的在功能中。 我所知道的只是在函数getClassOfVariable中我只得到像B这样的类。

感谢您的帮助! :)

2 个答案:

答案 0 :(得分:2)

你做不到。

在Python中,变量只是值的名称。值可以有多个名称,例如60可能被称为seconds_per_minuteminutes_per_hour,甚至speed_limit_mph,这些名称显然彼此无关。值也可以没有名称,例如print(60)不会给60任何名称。

要记住的一点是,当你调用一个函数时,你的参数是passed by assignment。也就是说,函数的参数成为您传入的值的新名称。因此被调用的函数不知道使用的是您传递的对象的名称,它只知道该对象的自己的名称

在这种情况下,对象本身不知道它在哪个类中创建。你知道它,因为你知道对象的名称(它是B().b)。但是对象的名称没有传递给被调用的函数,因此getClassOfVariable无法确定您的A对象是在哪个类中创建的。

那么,如何解决这个限制?最简单的方法是将此信息提供给构造函数中的A对象,方法是将type(self)(或self.__class__作为Python 2.x经典类)作为参数传递给{{1并在A()方法中处理它,如下所示:

A.__init__()

然后,您可以检查class A(): def __init__(self, owner=None): self.a = 1 self.owner = owner class B(): def __init__(self): self.b = A(type(self)) 属性以找出创建B().b.owner对象的类。但是,如果您创建A的子类,则B将是该子类而不是type(self)。如果在这种情况下仍然需要B,那么您应该通过B而不是B

答案 1 :(得分:0)

您可以为属性使用描述符。在描述符的__set__方法中,为其值添加一个属性,可以在函数内部进行检查。

from weakref import WeakKeyDictionary

class A:
    def __init__(self):
        self.a = 1

class X:
    """A descriptor that knows where it was defined"""
    def __init__(self, default):
        self.default = default
        self.data = WeakKeyDictionary()

    def __get__(self, instance, owner):
        # we get here when someone calls x.d, and d is an X instance
        # instance = x
        # owner = type(x)
        return self.data.get(instance, self.default)

    def __set__(self, instance, value):
        # we get here when someone calls x.d = val, and d is an X instance
        # add an attribute to the value and assign the instance
        #value.defining_class = instance
        value.defining_class = instance.__class__
        self.data[instance] = value

class B:
    b = X(None) 
    def __init__(self):
        self.b = A()

def getClassOfVariable(abc):
    print(f'abc: {abc}')
    print(f'defining_class: {abc.defining_class}')

getClassOfVariable(B().b)

结果:

abc: <__main__.A object at 0x.....>
defining_class: <class '__main__.B'>

我从Python Descriptors Demystified改编了这个描述符,在编写描述符时我总是引用它。

警告:虽然这有效,但这个感觉就像一个黑客,当然还没有经过测试的陷阱。在此示例中,A的实例添加了一个属性表示它已在B中定义;如果那个实例得到传递,它可能会丢失它的上下文,并且在内省时,添加的属性可能看起来确实很奇怪。 - 但是对于这个简单的例子,似乎没问题。也许有评论,甚至编辑的downvotes将阐明。添加属性似乎太容易了,也许应该有一些保护措施。或者value.defining_class可能只是字符串instance.__class__ - 为此而编辑