【问题标题】:Methods in python are associated with the class. what does a function associated directly with the instance imply?python 中的方法与类相关联。与实例直接关联的函数意味着什么?
【发布时间】:2019-04-25 18:50:52
【问题描述】:

我知道在 python 中,方法与类关联而不是实例,但它们接受实例作为第一个参数以便访问它。但是,仍然可以定义一个函数并将其直接绑定到一个实例。这意味着什么?这个函数能以某种方式访问​​实例吗?

class TestClass:
    def __init__(self, a):
       self.a = a

    def method1(self):
        return self.a

my_obj = TestClass(12)

print(my_obj.method1()) // 12

Python 也允许这样做:

class TestClass:
    def __init__(self, a):
       self.a = a
my_obj = TestClass(12)

def method1_defined_outside(self):
    return self.a

TestClass.method1 = method1_defined_outside

print(my_obj.method1()) // 12

上面的两个sn-ps是同一个意思。 但python也允许这样做:

class TestCase:
    def __init__(self, a):
       self.a = a
my_obj = TestCase(12)

def method1_defined_outside(self):
    return self.a

my_obj.method1 = method1_defined_outside

print(my_obj.method1()) // this throws an error stating the method1 is missing one postional argument(s), so clearly self does not automatically equate to the object

第二个sn-p和第三个sn-p的区别在于,外部定义的方法绑定到后者的实例,而绑定到前者的类。

【问题讨论】:

    标签: python python-3.x function class self


    【解决方案1】:

    当您通过实例访问方法,但该方法存在于类上时,访问该方法实际上会创建一个方法包装器。这个包装器知道调用该方法的实例,并将它作为第一个参数传递给实际函数(按照约定命名为self)。这背后的机制是descriptor protocol,它也是属性的工作方式。

    当您将方法直接放在实例上时,这些都不适用,它只是您通过实例访问的函数。它没有得到self

    现在,您可以通过手动调用描述符创建方法包装器,并在实例上设置生成的绑定方法。

    my_obj.method1 = method1_defined_outside.__get__(my_obj)
    

    现在my_obj.method1()my_obj 传递为self

    不过,您希望在这样的实例上设置方法的情况相当少见。

    【讨论】:

      【解决方案2】:

      您可以强制以self 发送实例的一种方法是使用functools.partial 包装器:

      from functools import partial
      
      class A:
          def __init__(self):
              self.x = 10
      
      a1 = A()
      
      def do_external(self):
          print("EXTERNAL", self.x)
      
      a1.doext = partial(do_external, a1)
      
      a1.doext()
      

      这将在控制台中产生:

      EXTERNAL 10
      

      【讨论】:

        猜你喜欢
        • 2010-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-08
        • 1970-01-01
        • 1970-01-01
        • 2019-07-23
        相关资源
        最近更新 更多