class A:

    def __init__(self, text):
        self.printStats()
        A.printStats(text)

    def printStats(self):
        print(self)

a = A("Hello")

Это печатает:

<A object at 0x7f47e2f08ac8>
Hello

Почему это (A.printStats(text)) возможно? Я понимаю, что происходит (self ссылается на text), но я не понимаю, почему.

4
d9h 9 Янв 2017 в 19:21

3 ответа

Лучший ответ

Когда вы создаете экземпляр класса:

a = A('some text')

Аргумент self становится постоянно связанным с a, это магия, стоящая за классами. Если вы попытаетесь a.printStats('something'), это вызовет ошибку, поскольку self аргумент уже занят a. Вы можете восстановить исходную функцию с несвязанным self с помощью a.printFunction.__func__. Попробуйте a.printFunction.__func__('this will be self argument')

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

A = {'__init__': someInitFunction,
     'printStats': printStatsFunction}

Вы должны помнить, что имя self является произвольным, и вы можете использовать любое слово, даже not_self.

1
Piotr Dabkowski 9 Янв 2017 в 16:33
A.printStats(text)

НЕ вызывает printStats с экземпляром A. Он вызывает его со строкой - self не передается.

def printStats(self):
    # <--- here, "self" if the string "Hello", not an instance of A.
    print(self)

A.printStats(self) эквивалентен self.printStats. Аналогично, если у вас есть функция printStatsWithPrefix;

class A:
    def printStatsWithPrefix(self, prefix):
        ...  # function body goes here

Вам придется сделать A.printStatsWithPrefix(self, prefix).


Примечание по стилю: По соглашению Python (PEP 8) вы должны использовать lowercase_with_underscores для имен функций.

4
noɥʇʎԀʎzɐɹƆ 9 Янв 2017 в 16:25

Ваш код потерпит неудачу в Python 2, так как вызов метода через класс требует, чтобы первый аргумент класса был фактически экземпляром класса.

В Python 3 реализация менее строгая, поскольку ожидается, что первый аргумент будет реализовывать только необходимый интерфейс, относящийся к экземпляру класса; проверка того, является ли параметр экземпляром, не выполняется. И поскольку вы на самом деле не обращаетесь к какому-либо методу / переменной экземпляра внутри printStats через self, это работает, и оно просто печатает переданную строку 'hello'.

1
Moses Koledoye 9 Янв 2017 в 16:49