Методы в python связаны с классом.что означает функция, связанная непосредственно с экземпляром? - PullRequest
1 голос
/ 25 апреля 2019

Я знаю, что в 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

Два приведенных выше фрагмента означают одно и то же.но 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

Разница между вторым и третьим фрагментом заключается в том, что метод, определенный снаружи, привязан к экземпляру в последнем и к классу в первом.

Ответы [ 2 ]

1 голос
/ 25 апреля 2019

Когда вы обращаетесь к методу через экземпляр, но метод живет в классе, доступ к методу фактически создает оболочку метода. Эта оболочка знает, к какому экземпляру был вызван метод, и передает ее фактической функции в качестве первого аргумента (именуемого, по соглашению, self). Механизм, лежащий в основе этого, - протокол дескриптора , и так же работают свойства.

Когда вы помещаете метод непосредственно в экземпляр, ничего из этого не применяется, и это просто функция, к которой вы обращаетесь через экземпляр. Не получается self.

Теперь вы можете создать упаковщик метода, вызвав дескриптор вручную, и установить полученный метод привязки для экземпляра.

my_obj.method1 = method1_defined_outside.__get__(my_obj)

Теперь my_obj.method1() передает my_obj как self.

Ситуации, в которых вы хотите установить метод для такого экземпляра, довольно редки.

0 голосов
/ 25 апреля 2019

Одним из способов принудительной отправки экземпляра как 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
...